aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Ava/UI/Helpers/MetalHelper.cs127
-rw-r--r--Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs28
-rw-r--r--Ryujinx.Ui.Common/Helper/ObjectiveC.cs97
-rw-r--r--Ryujinx.Ui.Common/Helper/OpenHelper.cs21
4 files changed, 141 insertions, 132 deletions
diff --git a/Ryujinx.Ava/UI/Helpers/MetalHelper.cs b/Ryujinx.Ava/UI/Helpers/MetalHelper.cs
deleted file mode 100644
index 5eb8660a..00000000
--- a/Ryujinx.Ava/UI/Helpers/MetalHelper.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-using System;
-using System.Runtime.Versioning;
-using System.Runtime.InteropServices;
-using Avalonia;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public delegate void UpdateBoundsCallbackDelegate(Rect rect);
-
- [SupportedOSPlatform("macos")]
- static partial class MetalHelper
- {
- private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
-
- private struct Selector
- {
- public readonly IntPtr NativePtr;
-
- public unsafe Selector(string value)
- {
- int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
- byte* data = stackalloc byte[size];
-
- fixed (char* pValue = value)
- {
- System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
- }
-
- NativePtr = sel_registerName(data);
- }
-
- public static implicit operator Selector(string value) => new Selector(value);
- }
-
- private static unsafe IntPtr GetClass(string value)
- {
- int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
- byte* data = stackalloc byte[size];
-
- fixed (char* pValue = value)
- {
- System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
- }
-
- return objc_getClass(data);
- }
-
- private struct NSPoint
- {
- public double X;
- public double Y;
-
- public NSPoint(double x, double y)
- {
- X = x;
- Y = y;
- }
- }
-
- private struct NSRect
- {
- public NSPoint Pos;
- public NSPoint Size;
-
- public NSRect(double x, double y, double width, double height)
- {
- Pos = new NSPoint(x, y);
- Size = new NSPoint(width, height);
- }
- }
-
- public static IntPtr GetMetalLayer(out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
- {
- // Create a new CAMetalLayer.
- IntPtr layerClass = GetClass("CAMetalLayer");
- IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
- objc_msgSend(metalLayer, "init");
-
- // Create a child NSView to render into.
- IntPtr nsViewClass = GetClass("NSView");
- IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
- objc_msgSend(child, "init", new NSRect(0, 0, 0, 0));
-
- // Make its renderer our metal layer.
- objc_msgSend(child, "setWantsLayer:", (byte)1);
- objc_msgSend(child, "setLayer:", metalLayer);
- objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
-
- // Ensure the scale factor is up to date.
- updateBounds = (Rect rect) => {
- objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
- };
-
- nsView = child;
- return metalLayer;
- }
-
- public static void DestroyMetalLayer(IntPtr nsView, IntPtr metalLayer)
- {
- // TODO
- }
-
- [LibraryImport(LibObjCImport)]
- private static unsafe partial IntPtr sel_registerName(byte* data);
-
- [LibraryImport(LibObjCImport)]
- private static unsafe partial IntPtr objc_getClass(byte* data);
-
- [LibraryImport(LibObjCImport)]
- private static partial void objc_msgSend(IntPtr receiver, Selector selector);
-
- [LibraryImport(LibObjCImport)]
- private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
-
- [LibraryImport(LibObjCImport)]
- private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
-
- [LibraryImport(LibObjCImport)]
- private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
-
- [LibraryImport(LibObjCImport)]
- private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
-
- [LibraryImport(LibObjCImport, EntryPoint = "objc_msgSend")]
- private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs b/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
index 532f4dc2..a5c8b003 100644
--- a/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
+++ b/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
@@ -2,9 +2,9 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform;
-using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Configuration;
using Ryujinx.Ui.Common.Configuration;
+using Ryujinx.Ui.Common.Helper;
using SPB.Graphics;
using SPB.Platform;
using SPB.Platform.GLX;
@@ -30,6 +30,7 @@ namespace Ryujinx.Ava.UI.Renderer
protected IntPtr NsView { get; set; }
protected IntPtr MetalLayer { get; set; }
+ public delegate void UpdateBoundsCallbackDelegate(Rect rect);
private UpdateBoundsCallbackDelegate _updateBoundsCallback;
public event EventHandler<IntPtr> WindowCreated;
@@ -237,8 +238,29 @@ namespace Ryujinx.Ava.UI.Renderer
[SupportedOSPlatform("macos")]
IPlatformHandle CreateMacOS()
{
- MetalLayer = MetalHelper.GetMetalLayer(out IntPtr nsView, out _updateBoundsCallback);
+ // Create a new CAMetalLayer.
+ IntPtr layerClass = ObjectiveC.objc_getClass("CAMetalLayer");
+ IntPtr metalLayer = ObjectiveC.IntPtr_objc_msgSend(layerClass, "alloc");
+ ObjectiveC.objc_msgSend(metalLayer, "init");
+
+ // Create a child NSView to render into.
+ IntPtr nsViewClass = ObjectiveC.objc_getClass("NSView");
+ IntPtr child = ObjectiveC.IntPtr_objc_msgSend(nsViewClass, "alloc");
+ ObjectiveC.objc_msgSend(child, "init", new ObjectiveC.NSRect(0, 0, 0, 0));
+
+ // Make its renderer our metal layer.
+ ObjectiveC.objc_msgSend(child, "setWantsLayer:", 1);
+ ObjectiveC.objc_msgSend(child, "setLayer:", metalLayer);
+ ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
+
+ // Ensure the scale factor is up to date.
+ _updateBoundsCallback = rect =>
+ {
+ ObjectiveC.objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
+ };
+ IntPtr nsView = child;
+ MetalLayer = metalLayer;
NsView = nsView;
return new PlatformHandle(nsView, "NSView");
@@ -260,7 +282,7 @@ namespace Ryujinx.Ava.UI.Renderer
[SupportedOSPlatform("macos")]
void DestroyMacOS()
{
- MetalHelper.DestroyMetalLayer(NsView, MetalLayer);
+ // TODO
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Ui.Common/Helper/ObjectiveC.cs b/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
new file mode 100644
index 00000000..234f7597
--- /dev/null
+++ b/Ryujinx.Ui.Common/Helper/ObjectiveC.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Text;
+
+namespace Ryujinx.Ui.Common.Helper
+{
+ [SupportedOSPlatform("macos")]
+ public static partial class ObjectiveC
+ {
+ private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
+
+ [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
+ private static unsafe partial IntPtr sel_getUid(string name);
+
+ [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)]
+ public static partial IntPtr objc_getClass(string name);
+
+ [LibraryImport(ObjCRuntime)]
+ public static partial void objc_msgSend(IntPtr receiver, Selector selector);
+
+ [LibraryImport(ObjCRuntime)]
+ public static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
+
+ [LibraryImport(ObjCRuntime)]
+ public static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
+
+ [LibraryImport(ObjCRuntime)]
+ public static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
+
+ [LibraryImport(ObjCRuntime)]
+ public static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
+
+ [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+ public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
+
+ [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+ public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
+
+ [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param);
+
+ [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param);
+
+ public struct Selector
+ {
+ public readonly IntPtr SelPtr;
+
+ public unsafe Selector(string name)
+ {
+ SelPtr = sel_getUid(name);
+ }
+
+ public static implicit operator Selector(string value) => new(value);
+ }
+
+ public struct NSString
+ {
+ public readonly IntPtr StrPtr;
+
+ public NSString(string aString)
+ {
+ IntPtr nsString = objc_getClass("NSString");
+ StrPtr = IntPtr_objc_msgSend(nsString, "stringWithUTF8String:", aString);
+ }
+
+ public static implicit operator IntPtr(NSString nsString) => nsString.StrPtr;
+ }
+
+ public readonly struct NSPoint
+ {
+ public readonly double X;
+ public readonly double Y;
+
+ public NSPoint(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+ }
+
+ public readonly struct NSRect
+ {
+ public readonly NSPoint Pos;
+ public readonly NSPoint Size;
+
+ public NSRect(double x, double y, double width, double height)
+ {
+ Pos = new NSPoint(x, y);
+ Size = new NSPoint(width, height);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Ui.Common/Helper/OpenHelper.cs b/Ryujinx.Ui.Common/Helper/OpenHelper.cs
index 35534892..5b2e8663 100644
--- a/Ryujinx.Ui.Common/Helper/OpenHelper.cs
+++ b/Ryujinx.Ui.Common/Helper/OpenHelper.cs
@@ -55,7 +55,17 @@ namespace Ryujinx.Ui.Common.Helper
}
else if (OperatingSystem.IsMacOS())
{
- Process.Start("open", $"-R \"{path}\"");
+ ObjectiveC.NSString nsStringPath = new(path);
+ IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
+ var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "fileURLWithPath:", nsStringPath);
+
+ IntPtr nsArray = ObjectiveC.objc_getClass("NSArray");
+ IntPtr urlArray = ObjectiveC.IntPtr_objc_msgSend(nsArray, "arrayWithObject:", urlPtr);
+
+ IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
+ IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
+
+ ObjectiveC.objc_msgSend(sharedWorkspace, "activateFileViewerSelectingURLs:", urlArray);
}
else if (OperatingSystem.IsLinux())
{
@@ -84,7 +94,14 @@ namespace Ryujinx.Ui.Common.Helper
}
else if (OperatingSystem.IsMacOS())
{
- Process.Start("open", url);
+ ObjectiveC.NSString nsStringPath = new(url);
+ IntPtr nsUrl = ObjectiveC.objc_getClass("NSURL");
+ var urlPtr = ObjectiveC.IntPtr_objc_msgSend(nsUrl, "URLWithString:", nsStringPath);
+
+ IntPtr nsWorkspace = ObjectiveC.objc_getClass("NSWorkspace");
+ IntPtr sharedWorkspace = ObjectiveC.IntPtr_objc_msgSend(nsWorkspace, "sharedWorkspace");
+
+ ObjectiveC.bool_objc_msgSend(sharedWorkspace, "openURL:", urlPtr);
}
else
{