Pārlūkot izejas kodu

Platform dependend stuff wip

flabbet 1 gadu atpakaļ
vecāks
revīzija
2db5b854ea

+ 15 - 82
src/PixiEditor.AvaloniaUI/Initialization/ClassicDesktopEntry.cs

@@ -24,18 +24,6 @@ namespace PixiEditor.AvaloniaUI.Initialization;
 
 internal class ClassicDesktopEntry
 {
-    /// <summary>The event mutex name.</summary>
-    private const string UniqueEventName = "33f1410b-2ad7-412a-a468-34fe0a85747c";
-
-    /// <summary>The unique mutex name.</summary>
-    private const string UniqueMutexName = "ab2afe27-b9ee-4f03-a1e4-c18da16a349c";
-
-    /// <summary>The event wait handle.</summary>
-    private EventWaitHandle _eventWaitHandle;
-
-    private string passedArgsFile = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
-        "PixiEditor", ".passedArgs");
-
     private IClassicDesktopStyleApplicationLifetime desktop;
 
     public ClassicDesktopEntry(IClassicDesktopStyleApplicationLifetime desktop)
@@ -45,9 +33,6 @@ internal class ClassicDesktopEntry
         desktop.ShutdownRequested += ShutdownRequested;
     }
 
-    /// <summary>The mutex.</summary>
-    private Mutex _mutex;
-
     private void Start(object? sender, ControlledApplicationLifetimeStartupEventArgs e)
     {
         StartupArgs.Args = e.Args.ToList();
@@ -78,6 +63,7 @@ internal class ClassicDesktopEntry
         }
 
         Dispatcher dispatcher = Dispatcher.UIThread;
+        InitOperatingSystem();
 
 #if !STEAM
         if (!HandleNewInstance(dispatcher))
@@ -86,7 +72,6 @@ internal class ClassicDesktopEntry
         }
 #endif
 
-        InitOperatingSystem();
         var extensionLoader = InitApp();
 
         desktop.MainWindow = new MainWindow(extensionLoader);
@@ -146,79 +131,27 @@ internal class ClassicDesktopEntry
 
     private bool HandleNewInstance(Dispatcher? dispatcher)
     {
-        bool isOwned;
-        _mutex = new Mutex(true, UniqueMutexName, out isOwned);
-        _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName);
-
-        GC.KeepAlive(_mutex);
-
-        if (dispatcher == null)
-            return true;
-
-        if (isOwned)
-        {
-            var thread = new Thread(
-                () =>
-                {
-                    while (_eventWaitHandle.WaitOne())
-                    {
-                        dispatcher.Invoke(
-                            (Action)(() =>
-                            {
-                                if (desktop.MainWindow is MainWindow mainWindow)
-                                {
-                                    mainWindow.BringIntoView();
-                                    List<string> args = new List<string>();
-                                    if (File.Exists(passedArgsFile))
-                                    {
-                                        args = CommandLineHelpers.SplitCommandLine(File.ReadAllText(passedArgsFile))
-                                            .ToList();
-                                        File.Delete(passedArgsFile);
-                                    }
-
-                                    StartupArgs.Args = args;
-                                    StartupArgs.Args.Add("--openedInExisting");
-                                    ViewModelMain viewModel = (ViewModelMain)mainWindow.DataContext;
-                                    viewModel.StartupCommand.Execute(null);
-                                }
-                            }));
-                    }
-                })
-            {
-                // It is important mark it as background otherwise it will prevent app from exiting.
-                IsBackground = true
-            };
-
-            thread.Start();
-            return true;
-        }
-
-        // Notify other instance so it could bring itself to foreground.
-        File.WriteAllText(passedArgsFile, string.Join(' ', WrapSpaces(Environment.GetCommandLineArgs())));
-        _eventWaitHandle.Set();
-
-        // Terminate this instance.
-        desktop.Shutdown();
-        return false;
+        return IOperatingSystem.Current.HandleNewInstance(dispatcher, OpenInExisting, desktop);
     }
 
-    private string?[] WrapSpaces(string[] args)
+    private void OpenInExisting(string passedArgsFile)
     {
-        string?[] wrappedArgs = new string?[args.Length];
-        for (int i = 0; i < args.Length; i++)
+        if (desktop.MainWindow is MainWindow mainWindow)
         {
-            string arg = args[i];
-            if (arg.Contains(' '))
-            {
-                wrappedArgs[i] = $"\"{arg}\"";
-            }
-            else
+            mainWindow.BringIntoView();
+            List<string> args = new List<string>();
+            if (File.Exists(passedArgsFile))
             {
-                wrappedArgs[i] = arg;
+                args = CommandLineHelpers.SplitCommandLine(File.ReadAllText(passedArgsFile))
+                    .ToList();
+                File.Delete(passedArgsFile);
             }
-        }
 
-        return wrappedArgs;
+            StartupArgs.Args = args;
+            StartupArgs.Args.Add("--openedInExisting");
+            ViewModelMain viewModel = (ViewModelMain)mainWindow.DataContext;
+            viewModel.StartupCommand.Execute(null);
+        }
     }
 
     private bool ParseArgument(string pattern, string args, out Group[] groups)

+ 2 - 2
src/PixiEditor.AvaloniaUI/Views/LoadingWindow.axaml.cs

@@ -15,10 +15,10 @@ public partial class LoadingWindow : Window
 
     public static void ShowInNewThread()
     {
-        var thread = new Thread(ThreadStart) { IsBackground = true };
+        /*var thread = new Thread(ThreadStart) { IsBackground = true };
 
         thread.SetApartmentState(ApartmentState.STA);
-        thread.Start();
+        thread.Start();*/
     }
 
     public void SafeClose()

+ 8 - 1
src/PixiEditor.Linux/LinuxOperatingSystem.cs

@@ -1,4 +1,6 @@
-using PixiEditor.OperatingSystem;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Threading;
+using PixiEditor.OperatingSystem;
 
 namespace PixiEditor.Linux;
 
@@ -17,4 +19,9 @@ public sealed class LinuxOperatingSystem : IOperatingSystem
     {
         throw new NotImplementedException();
     }
+
+    public bool HandleNewInstance(Dispatcher? dispatcher, Action<string> openInExistingAction, IApplicationLifetime lifetime)
+    {
+        return true;
+    }
 }

+ 8 - 1
src/PixiEditor.MacOs/MacOperatingSystem.cs

@@ -1,4 +1,6 @@
-using PixiEditor.OperatingSystem;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Threading;
+using PixiEditor.OperatingSystem;
 
 namespace PixiEditor.MacOs;
 
@@ -16,4 +18,9 @@ public sealed class MacOperatingSystem : IOperatingSystem
     {
         throw new NotImplementedException();
     }
+
+    public bool HandleNewInstance(Dispatcher? dispatcher, Action<string> openInExistingAction, IApplicationLifetime lifetime)
+    {
+        throw new NotImplementedException();
+    }
 }

+ 5 - 1
src/PixiEditor.OperatingSystem/IOperatingSystem.cs

@@ -1,4 +1,7 @@
-namespace PixiEditor.OperatingSystem;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Threading;
+
+namespace PixiEditor.OperatingSystem;
 
 public interface IOperatingSystem
 {
@@ -20,4 +23,5 @@ public interface IOperatingSystem
 
     public void OpenUri(string uri);
     public void OpenFolder(string path);
+    public bool HandleNewInstance(Dispatcher? dispatcher, Action<string> openInExistingAction, IApplicationLifetime lifetime);
 }

+ 72 - 0
src/PixiEditor.Windows/WindowsOperatingSystem.cs

@@ -1,4 +1,6 @@
 using System.Runtime.InteropServices;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Threading;
 using PixiEditor.Helpers;
 using PixiEditor.OperatingSystem;
 
@@ -9,6 +11,18 @@ public sealed class WindowsOperatingSystem : IOperatingSystem
     public string Name => "Windows";
     public IInputKeys InputKeys { get; } = new WindowsInputKeys();
     public IProcessUtility ProcessUtility { get; } = new WindowsProcessUtility();
+    
+    private const string UniqueEventName = "33f1410b-2ad7-412a-a468-34fe0a85747c";
+    
+    private const string UniqueMutexName = "ab2afe27-b9ee-4f03-a1e4-c18da16a349c";
+    
+    private EventWaitHandle _eventWaitHandle;
+    
+    private Mutex _mutex;
+    
+    private string passedArgsFile = Path.Join(
+        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+        "PixiEditor", ".passedArgs");
 
     public void OpenUri(string uri)
     {
@@ -33,4 +47,62 @@ public sealed class WindowsOperatingSystem : IOperatingSystem
 
         WindowsProcessUtility.ShellExecuteEV(dirName);
     }
+
+    public bool HandleNewInstance(Dispatcher? dispatcher, Action<string> openInExistingAction, IApplicationLifetime lifetime)
+    {
+        bool isOwned;
+        _mutex = new Mutex(true, UniqueMutexName, out isOwned);
+        _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName);
+
+        GC.KeepAlive(_mutex);
+
+        if (dispatcher == null)
+            return true;
+
+        if (isOwned)
+        {
+            var thread = new Thread(
+                () =>
+                {
+                    while (_eventWaitHandle.WaitOne())
+                    {
+                        dispatcher.Invoke(() => openInExistingAction(passedArgsFile));
+                    }
+                })
+            {
+                // It is important mark it as background otherwise it will prevent app from exiting.
+                IsBackground = true
+            };
+
+            thread.Start();
+            return true;
+        }
+
+        // Notify other instance so it could bring itself to foreground.
+        File.WriteAllText(passedArgsFile, string.Join(' ', WrapSpaces(Environment.GetCommandLineArgs())));
+        _eventWaitHandle.Set();
+
+        // Terminate this instance.
+        (lifetime as IClassicDesktopStyleApplicationLifetime)!.Shutdown();
+        return false;
+    }
+    
+    private string?[] WrapSpaces(string[] args)
+    {
+        string?[] wrappedArgs = new string?[args.Length];
+        for (int i = 0; i < args.Length; i++)
+        {
+            string arg = args[i];
+            if (arg.Contains(' '))
+            {
+                wrappedArgs[i] = $"\"{arg}\"";
+            }
+            else
+            {
+                wrappedArgs[i] = arg;
+            }
+        }
+
+        return wrappedArgs;
+    }
 }