From 9f3394ad3069198dd40be623d99210fa40bbb6c0 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Thu, 1 Jan 2026 09:18:43 -0500 Subject: [PATCH 01/12] UI: Included more launch checks Windows: - Check for OneDrive install path. macOS: - Check for root (needs testing). Linux: - Check for root. - Check for flatpak. --- src/Ryujinx/Program.cs | 96 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index d77e79756..d0560f72d 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -52,17 +52,35 @@ namespace Ryujinx.Ava { if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", + $"Ryujinx {Version}", MbIconwarning); return 0; } - var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + string onedriveFiles = Environment.GetEnvironmentVariable("Onedrive"); + string onedriveConsumerFiles = Environment.GetEnvironmentVariable("OnedriveConsumer"); + string onedriveCommercialFiles = Environment.GetEnvironmentVariable("OnedriveCommercial"); + + if (Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveFiles) + || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveConsumerFiles) + || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveCommercialFiles)) + { + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "Ryujinx is not intended to be run from a OneDrive folder. Please move it out and relaunch.", + $"Ryujinx {Version}", MbIconwarning); + return 0; + } + + string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); if (Environment.CurrentDirectory.StartsWithIgnoreCase(programFiles) || Environment.CurrentDirectory.StartsWithIgnoreCase(programFilesX86)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run from the Program Files folder. Please move it out and relaunch.", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "Ryujinx is not intended to be run from the Program Files folder. Please move it out and relaunch.", + $"Ryujinx {Version}", MbIconwarning); return 0; } @@ -72,10 +90,78 @@ namespace Ryujinx.Ava // ...but this reads like it checks if the current is in/has the Windows admin role? lol if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run as administrator.", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run as administrator.", + $"Ryujinx {Version}", MbIconwarning); return 0; } } + else + { + + // Unix + [DllImport("libc")] + static extern uint geteuid(); + + bool root = geteuid().Equals(0); + + if (OperatingSystem.IsMacOS()) + { + // If you add a check here, please, for the love of god, check it BEFORE loading the dialog. + if (root) + { + // Grab what we need to make the message box. + const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; + const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; + + [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] + static extern IntPtr GetSelector(string name); + + [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] + static extern IntPtr GetClass(string name); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessage(IntPtr target, IntPtr selector); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); + + IntPtr NSStringClass = GetClass("NSString"); + IntPtr Selector = GetSelector("stringWithUTF8String:"); + IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + + // Create caption and text. + IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); + IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); + + // Set up the message box. + SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), caption); + SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), text); + SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), Marshal.StringToHGlobalAnsi("OK")); + + // Send prompt to user, then clean up. + SendMessage(AlertInstance, GetSelector("runModal")); + + SendMessage(AlertInstance, GetSelector("release")); + + return 0; + } + } + + if (OperatingSystem.IsLinux()) + { + if (root) + { + Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + return 0; + } + + if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) + { + Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); + Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official AppImage or tarball."); + } + } + } bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui"); bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps"); From 89487d67c4809e8b69b854325f4b8a4831128e8c Mon Sep 17 00:00:00 2001 From: Shyanne Date: Thu, 1 Jan 2026 15:10:53 -0500 Subject: [PATCH 02/12] Added links to flatpak check --- src/Ryujinx/Program.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index d0560f72d..f58a356d3 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -158,7 +158,11 @@ namespace Ryujinx.Ava if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) { Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); - Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official AppImage or tarball."); + Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official builds."); + Logger.Info?.PrintMsg(LogClass.Application, + "AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); + Logger.Info?.PrintMsg(LogClass.Application, + "Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); } } } From 8b7c228cf7b456743e9627cec1d1437ba2b5fda2 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Fri, 2 Jan 2026 15:54:42 -0500 Subject: [PATCH 03/12] added some debugging and fix for fs --- src/Ryujinx/Program.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index f58a356d3..34938fd64 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -109,13 +109,16 @@ namespace Ryujinx.Ava // If you add a check here, please, for the love of god, check it BEFORE loading the dialog. if (root) { + Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); // Grab what we need to make the message box. const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; + Console.Write("Set strings for library fetch."); + [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] static extern IntPtr GetSelector(string name); - + [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] static extern IntPtr GetClass(string name); @@ -124,11 +127,15 @@ namespace Ryujinx.Ava [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); + + Console.Write("Set up DLL Imports."); IntPtr NSStringClass = GetClass("NSString"); IntPtr Selector = GetSelector("stringWithUTF8String:"); IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + Console.Write("Set up necessary classes and instances."); + // Create caption and text. IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); @@ -141,8 +148,14 @@ namespace Ryujinx.Ava // Send prompt to user, then clean up. SendMessage(AlertInstance, GetSelector("runModal")); + Console.Write($"AlertInstance: {AlertInstance}"); + + Console.Write("Sent message box to macOS."); + SendMessage(AlertInstance, GetSelector("release")); + Console.Write("Cleaned up."); + return 0; } } @@ -158,11 +171,13 @@ namespace Ryujinx.Ava if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) { Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); + Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official builds."); Logger.Info?.PrintMsg(LogClass.Application, - "AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); + " AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, - "Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + " Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); } } } @@ -203,6 +218,8 @@ namespace Ryujinx.Ava .UsePlatformDetect() .With(new X11PlatformOptions { + UseDBusMenu = false, + UseDBusFilePicker = false, EnableMultiTouch = true, EnableIme = true, EnableInputFocusProxy = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP") == "gamescope", From e92b4fdd053e15dfdcfe30de946a10166371af8d Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 3 Jan 2026 13:50:27 -0500 Subject: [PATCH 04/12] fixed the boxes fr this time --- src/Ryujinx/Program.cs | 63 ++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 34938fd64..bd86da781 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -110,11 +110,11 @@ namespace Ryujinx.Ava if (root) { Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + // Grab what we need to make the message box. const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; - - Console.Write("Set strings for library fetch."); + const string AppKitFramework = "/System/Library/Frameworks/AppKit.framework/AppKit"; [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] static extern IntPtr GetSelector(string name); @@ -127,44 +127,65 @@ namespace Ryujinx.Ava [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); - - Console.Write("Set up DLL Imports."); + [DllImport(ObjCRuntime)] + static extern IntPtr dlopen(string path, int mode); + + dlopen(AppKitFramework, 0x1); // have to invoke AppKit so that NSAlert doesn't return a null pointer + IntPtr NSStringClass = GetClass("NSString"); IntPtr Selector = GetSelector("stringWithUTF8String:"); - IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + IntPtr SharedApp = SendMessage(GetClass("NSApplication"), GetSelector("sharedApplication")); + IntPtr NSAlert = SendMessage(GetClass("NSAlert"), GetSelector("alloc")); + IntPtr AlertInstance = SendMessage(NSAlert, GetSelector("init")); - Console.Write("Set up necessary classes and instances."); - - // Create caption and text. + // Create caption, text, and button text. + // If you add a check, you can switch text with the check reason. IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); - + IntPtr button = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("OK")); + + // Set up the window. + SendMessageWithParameter(SharedApp, GetSelector("setActivationPolicy:"), (IntPtr) 0); // Give it a window. + SendMessageWithParameter(SharedApp, GetSelector("activateIgnoringOtherApps:"), (IntPtr) 1); // Force it to the front. + // Set up the message box. + SendMessageWithParameter(AlertInstance, GetSelector("setAlertStyle:"), (IntPtr)0); // Set style to warning. SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), caption); SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), text); - SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), Marshal.StringToHGlobalAnsi("OK")); + SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), button); // Send prompt to user, then clean up. SendMessage(AlertInstance, GetSelector("runModal")); - - Console.Write($"AlertInstance: {AlertInstance}"); - - Console.Write("Sent message box to macOS."); - SendMessage(AlertInstance, GetSelector("release")); - Console.Write("Cleaned up."); - return 0; } } if (OperatingSystem.IsLinux()) { - if (root) + if (!root) { - Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + + Console.WriteLine( + $"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + + const string sdl = "SDL2"; + + [DllImport(sdl)] + static extern int SDL_Init(uint flags); + + [DllImport(sdl, CallingConvention = CallingConvention.Cdecl)] + static extern int SDL_ShowSimpleMessageBox(uint flags, string title, string message, IntPtr window); + + [DllImport(sdl)] + static extern void SDL_Quit(); + + SDL_Init(0); + SDL_ShowSimpleMessageBox(32 /* 32 = warning style */, $"Ryujinx {Version}", "Ryujinx is not intended to be run as administrator.", IntPtr.Zero); + SDL_Quit(); + return 0; } @@ -176,7 +197,7 @@ namespace Ryujinx.Ava Logger.Info?.PrintMsg(LogClass.Application, " AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, - " Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + " Tarball >> https://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); } } @@ -413,7 +434,7 @@ namespace Ryujinx.Ava "never" => HideCursorMode.Never, "onidle" => HideCursorMode.OnIdle, "always" => HideCursorMode.Always, - _ => ConfigurationState.Instance.HideCursor, + _ => ConfigurationState.Instance.HideCursor }; // Check if memoryManagerMode was overridden. From 2bf306ea584af7ce338c5535773267248277a278 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Thu, 1 Jan 2026 09:18:43 -0500 Subject: [PATCH 05/12] UI: Included more launch checks Windows: - Check for OneDrive install path. macOS: - Check for root (needs testing). Linux: - Check for root. - Check for flatpak. --- src/Ryujinx/Program.cs | 96 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 8d03f81da..fe711cfda 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -53,17 +53,35 @@ namespace Ryujinx.Ava { if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", + $"Ryujinx {Version}", MbIconwarning); return 0; } - var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + string onedriveFiles = Environment.GetEnvironmentVariable("Onedrive"); + string onedriveConsumerFiles = Environment.GetEnvironmentVariable("OnedriveConsumer"); + string onedriveCommercialFiles = Environment.GetEnvironmentVariable("OnedriveCommercial"); + + if (Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveFiles) + || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveConsumerFiles) + || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveCommercialFiles)) + { + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "Ryujinx is not intended to be run from a OneDrive folder. Please move it out and relaunch.", + $"Ryujinx {Version}", MbIconwarning); + return 0; + } + + string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); if (Environment.CurrentDirectory.StartsWithIgnoreCase(programFiles) || Environment.CurrentDirectory.StartsWithIgnoreCase(programFilesX86)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run from the Program Files folder. Please move it out and relaunch.", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, + "Ryujinx is not intended to be run from the Program Files folder. Please move it out and relaunch.", + $"Ryujinx {Version}", MbIconwarning); return 0; } @@ -73,10 +91,78 @@ namespace Ryujinx.Ava // ...but this reads like it checks if the current is in/has the Windows admin role? lol if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)) { - _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run as administrator.", $"Ryujinx {Version}", MbIconwarning); + _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run as administrator.", + $"Ryujinx {Version}", MbIconwarning); return 0; } } + else + { + + // Unix + [DllImport("libc")] + static extern uint geteuid(); + + bool root = geteuid().Equals(0); + + if (OperatingSystem.IsMacOS()) + { + // If you add a check here, please, for the love of god, check it BEFORE loading the dialog. + if (root) + { + // Grab what we need to make the message box. + const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; + const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; + + [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] + static extern IntPtr GetSelector(string name); + + [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] + static extern IntPtr GetClass(string name); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessage(IntPtr target, IntPtr selector); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); + + IntPtr NSStringClass = GetClass("NSString"); + IntPtr Selector = GetSelector("stringWithUTF8String:"); + IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + + // Create caption and text. + IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); + IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); + + // Set up the message box. + SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), caption); + SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), text); + SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), Marshal.StringToHGlobalAnsi("OK")); + + // Send prompt to user, then clean up. + SendMessage(AlertInstance, GetSelector("runModal")); + + SendMessage(AlertInstance, GetSelector("release")); + + return 0; + } + } + + if (OperatingSystem.IsLinux()) + { + if (root) + { + Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + return 0; + } + + if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) + { + Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); + Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official AppImage or tarball."); + } + } + } bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui"); bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps"); From f49029803a2e54fa5709adf5e63a1386801f3e93 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Thu, 1 Jan 2026 15:10:53 -0500 Subject: [PATCH 06/12] Added links to flatpak check --- src/Ryujinx/Program.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index fe711cfda..0a45aa2da 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -159,7 +159,11 @@ namespace Ryujinx.Ava if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) { Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); - Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official AppImage or tarball."); + Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official builds."); + Logger.Info?.PrintMsg(LogClass.Application, + "AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); + Logger.Info?.PrintMsg(LogClass.Application, + "Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); } } } From 6cd6c1ae18c99cd74b7f6bf3f0d0281669fa5ee8 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Fri, 2 Jan 2026 15:54:42 -0500 Subject: [PATCH 07/12] added some debugging and fix for fs --- src/Ryujinx/Program.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 0a45aa2da..692a85f9b 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -110,13 +110,16 @@ namespace Ryujinx.Ava // If you add a check here, please, for the love of god, check it BEFORE loading the dialog. if (root) { + Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); // Grab what we need to make the message box. const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; + Console.Write("Set strings for library fetch."); + [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] static extern IntPtr GetSelector(string name); - + [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] static extern IntPtr GetClass(string name); @@ -125,11 +128,15 @@ namespace Ryujinx.Ava [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); + + Console.Write("Set up DLL Imports."); IntPtr NSStringClass = GetClass("NSString"); IntPtr Selector = GetSelector("stringWithUTF8String:"); IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + Console.Write("Set up necessary classes and instances."); + // Create caption and text. IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); @@ -142,8 +149,14 @@ namespace Ryujinx.Ava // Send prompt to user, then clean up. SendMessage(AlertInstance, GetSelector("runModal")); + Console.Write($"AlertInstance: {AlertInstance}"); + + Console.Write("Sent message box to macOS."); + SendMessage(AlertInstance, GetSelector("release")); + Console.Write("Cleaned up."); + return 0; } } @@ -159,11 +172,13 @@ namespace Ryujinx.Ava if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) { Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); + Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); Logger.Info?.PrintMsg(LogClass.Application, "Please visit https://ryujinx.app/ for our official builds."); Logger.Info?.PrintMsg(LogClass.Application, - "AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); + " AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, - "Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + " Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); } } } @@ -204,6 +219,8 @@ namespace Ryujinx.Ava .UsePlatformDetect() .With(new X11PlatformOptions { + UseDBusMenu = false, + UseDBusFilePicker = false, EnableMultiTouch = true, EnableIme = true, EnableInputFocusProxy = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP") == "gamescope", From df7b940bb98494248ff35fde3f2c5ea2a859a0a9 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Sat, 3 Jan 2026 13:50:27 -0500 Subject: [PATCH 08/12] fixed the boxes fr this time --- src/Ryujinx/Program.cs | 63 ++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 692a85f9b..51f2154f8 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -111,11 +111,11 @@ namespace Ryujinx.Ava if (root) { Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + // Grab what we need to make the message box. const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; - - Console.Write("Set strings for library fetch."); + const string AppKitFramework = "/System/Library/Frameworks/AppKit.framework/AppKit"; [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] static extern IntPtr GetSelector(string name); @@ -128,44 +128,65 @@ namespace Ryujinx.Ava [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); - - Console.Write("Set up DLL Imports."); + [DllImport(ObjCRuntime)] + static extern IntPtr dlopen(string path, int mode); + + dlopen(AppKitFramework, 0x1); // have to invoke AppKit so that NSAlert doesn't return a null pointer + IntPtr NSStringClass = GetClass("NSString"); IntPtr Selector = GetSelector("stringWithUTF8String:"); - IntPtr AlertInstance = SendMessage(SendMessage(GetClass("NSAlert"), GetSelector("alloc")), GetSelector("init")); + IntPtr SharedApp = SendMessage(GetClass("NSApplication"), GetSelector("sharedApplication")); + IntPtr NSAlert = SendMessage(GetClass("NSAlert"), GetSelector("alloc")); + IntPtr AlertInstance = SendMessage(NSAlert, GetSelector("init")); - Console.Write("Set up necessary classes and instances."); - - // Create caption and text. + // Create caption, text, and button text. + // If you add a check, you can switch text with the check reason. IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); - + IntPtr button = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("OK")); + + // Set up the window. + SendMessageWithParameter(SharedApp, GetSelector("setActivationPolicy:"), (IntPtr) 0); // Give it a window. + SendMessageWithParameter(SharedApp, GetSelector("activateIgnoringOtherApps:"), (IntPtr) 1); // Force it to the front. + // Set up the message box. + SendMessageWithParameter(AlertInstance, GetSelector("setAlertStyle:"), (IntPtr)0); // Set style to warning. SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), caption); SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), text); - SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), Marshal.StringToHGlobalAnsi("OK")); + SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), button); // Send prompt to user, then clean up. SendMessage(AlertInstance, GetSelector("runModal")); - - Console.Write($"AlertInstance: {AlertInstance}"); - - Console.Write("Sent message box to macOS."); - SendMessage(AlertInstance, GetSelector("release")); - Console.Write("Cleaned up."); - return 0; } } if (OperatingSystem.IsLinux()) { - if (root) + if (!root) { - Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + + Console.WriteLine( + $"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); + + const string sdl = "SDL2"; + + [DllImport(sdl)] + static extern int SDL_Init(uint flags); + + [DllImport(sdl, CallingConvention = CallingConvention.Cdecl)] + static extern int SDL_ShowSimpleMessageBox(uint flags, string title, string message, IntPtr window); + + [DllImport(sdl)] + static extern void SDL_Quit(); + + SDL_Init(0); + SDL_ShowSimpleMessageBox(32 /* 32 = warning style */, $"Ryujinx {Version}", "Ryujinx is not intended to be run as administrator.", IntPtr.Zero); + SDL_Quit(); + return 0; } @@ -177,7 +198,7 @@ namespace Ryujinx.Ava Logger.Info?.PrintMsg(LogClass.Application, " AppImage >> https://update.ryujinx.app/download/query?os=linuxappimage&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, - " Tarball >> http://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); + " Tarball >> https://update.ryujinx.app/download/query?os=linux&arch=x64&rc=stable"); Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); } } @@ -414,7 +435,7 @@ namespace Ryujinx.Ava "never" => HideCursorMode.Never, "onidle" => HideCursorMode.OnIdle, "always" => HideCursorMode.Always, - _ => ConfigurationState.Instance.HideCursor, + _ => ConfigurationState.Instance.HideCursor }; // Check if memoryManagerMode was overridden. From 068c654d953606c7d51659369d031862274697cd Mon Sep 17 00:00:00 2001 From: Shyanne Date: Mon, 5 Jan 2026 15:50:37 -0500 Subject: [PATCH 09/12] added null check for onedrive separated out native interop to respective classes/methods --- src/Ryujinx/Program.cs | 100 ++++-------------- .../Helpers/Converters/macOSNativeInterop.cs | 62 +++++++++++ src/Ryujinx/UI/Helpers/LinuxSDLInterop.cs | 30 ++++++ 3 files changed, 112 insertions(+), 80 deletions(-) create mode 100644 src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs create mode 100644 src/Ryujinx/UI/Helpers/LinuxSDLInterop.cs diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index bd86da781..bccc10516 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Ava { if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)) { + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run on an outdated version of Windows. Exiting..."); _ = Win32NativeInterop.MessageBoxA(nint.Zero, "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", $"Ryujinx {Version}", MbIconwarning); @@ -62,10 +63,12 @@ namespace Ryujinx.Ava string onedriveConsumerFiles = Environment.GetEnvironmentVariable("OnedriveConsumer"); string onedriveCommercialFiles = Environment.GetEnvironmentVariable("OnedriveCommercial"); - if (Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveFiles) - || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveConsumerFiles) - || Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveCommercialFiles)) + // Apparently not everyone has OneDrive shoved onto their system. + if ((onedriveFiles is not null && Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveFiles)) + || (onedriveConsumerFiles is not null && Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveConsumerFiles)) + || (onedriveCommercialFiles is not null && Environment.CurrentDirectory.StartsWithIgnoreCase(onedriveCommercialFiles))) { + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run from a OneDrive folder. Exiting..."); _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run from a OneDrive folder. Please move it out and relaunch.", $"Ryujinx {Version}", MbIconwarning); @@ -78,6 +81,7 @@ namespace Ryujinx.Ava if (Environment.CurrentDirectory.StartsWithIgnoreCase(programFiles) || Environment.CurrentDirectory.StartsWithIgnoreCase(programFilesX86)) { + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run from the Program Files folder. Exiting..."); _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run from the Program Files folder. Please move it out and relaunch.", $"Ryujinx {Version}", MbIconwarning); @@ -90,106 +94,42 @@ namespace Ryujinx.Ava // ...but this reads like it checks if the current is in/has the Windows admin role? lol if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)) { + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run as administrator. Exiting..."); _ = Win32NativeInterop.MessageBoxA(nint.Zero, "Ryujinx is not intended to be run as administrator.", $"Ryujinx {Version}", MbIconwarning); return 0; } } - else + else // Unix { - - // Unix + // sudo check [DllImport("libc")] static extern uint geteuid(); - bool root = geteuid().Equals(0); if (OperatingSystem.IsMacOS()) { - // If you add a check here, please, for the love of god, check it BEFORE loading the dialog. if (root) { - Console.WriteLine($"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); - - // Grab what we need to make the message box. - const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; - const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; - const string AppKitFramework = "/System/Library/Frameworks/AppKit.framework/AppKit"; - - [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] - static extern IntPtr GetSelector(string name); - - [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] - static extern IntPtr GetClass(string name); - - [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] - static extern IntPtr SendMessage(IntPtr target, IntPtr selector); - - [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] - static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); - - [DllImport(ObjCRuntime)] - static extern IntPtr dlopen(string path, int mode); - - dlopen(AppKitFramework, 0x1); // have to invoke AppKit so that NSAlert doesn't return a null pointer - - IntPtr NSStringClass = GetClass("NSString"); - IntPtr Selector = GetSelector("stringWithUTF8String:"); - IntPtr SharedApp = SendMessage(GetClass("NSApplication"), GetSelector("sharedApplication")); - IntPtr NSAlert = SendMessage(GetClass("NSAlert"), GetSelector("alloc")); - IntPtr AlertInstance = SendMessage(NSAlert, GetSelector("init")); - - // Create caption, text, and button text. - // If you add a check, you can switch text with the check reason. - IntPtr caption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi($"Ryujinx {Version}")); - IntPtr text = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("Ryujinx is not intended to be run as administrator.")); - IntPtr button = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi("OK")); - - // Set up the window. - SendMessageWithParameter(SharedApp, GetSelector("setActivationPolicy:"), (IntPtr) 0); // Give it a window. - SendMessageWithParameter(SharedApp, GetSelector("activateIgnoringOtherApps:"), (IntPtr) 1); // Force it to the front. - - // Set up the message box. - SendMessageWithParameter(AlertInstance, GetSelector("setAlertStyle:"), (IntPtr)0); // Set style to warning. - SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), caption); - SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), text); - SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), button); - - // Send prompt to user, then clean up. - SendMessage(AlertInstance, GetSelector("runModal")); - SendMessage(AlertInstance, GetSelector("release")); - + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run as administrator. Exiting..."); + macOSNativeInterop.SimpleMessageBox($"Ryujinx {Version}", + "Ryujinx is not intended to be run as administrator.", "Ok"); return 0; } } if (OperatingSystem.IsLinux()) { - if (!root) + if (root) { - - Console.WriteLine( - $"Ryujinx {Version}: Ryujinx is not intended to be run as administrator. Exiting..."); - - const string sdl = "SDL2"; - - [DllImport(sdl)] - static extern int SDL_Init(uint flags); - - [DllImport(sdl, CallingConvention = CallingConvention.Cdecl)] - static extern int SDL_ShowSimpleMessageBox(uint flags, string title, string message, IntPtr window); - - [DllImport(sdl)] - static extern void SDL_Quit(); - - SDL_Init(0); - SDL_ShowSimpleMessageBox(32 /* 32 = warning style */, $"Ryujinx {Version}", "Ryujinx is not intended to be run as administrator.", IntPtr.Zero); - SDL_Quit(); - + Logger.Error?.PrintMsg(LogClass.Application, "Ryujinx is not intended to be run as administrator. Exiting..."); + LinuxSDLInterop.SimpleMessageBox($"Ryujinx {Version}", "Ryujinx is not intended to be run as administrator."); return 0; } - - if (Environment.GetEnvironmentVariable("container").EqualsIgnoreCase("flatpak")) + + string container = Environment.GetEnvironmentVariable("container"); + + if (container is not null && container.EqualsIgnoreCase("flatpak")) { Logger.Warning?.PrintMsg(LogClass.Application, "This is very likely an unofficial build, Ryujinx does NOT have a flatpak!"); Logger.Info?.PrintMsg(LogClass.Application, "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); diff --git a/src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs b/src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs new file mode 100644 index 000000000..6dda1c823 --- /dev/null +++ b/src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs @@ -0,0 +1,62 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Ava.UI.Helpers +{ + public class macOSNativeInterop + { + // TODO: add a parameter for prompt style + // TODO: check success of prompt box + public static int SimpleMessageBox(string caption, string text, string button) + { + + // Grab what we need to make the message box. + const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; + const string FoundationFramework = "/System/Library/Frameworks/Foundation.framework/Foundation"; + const string AppKitFramework = "/System/Library/Frameworks/AppKit.framework/AppKit"; + + [DllImport(ObjCRuntime, EntryPoint = "sel_registerName")] + static extern IntPtr GetSelector(string name); + + [DllImport(ObjCRuntime, EntryPoint = "objc_getClass")] + static extern IntPtr GetClass(string name); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessage(IntPtr target, IntPtr selector); + + [DllImport(FoundationFramework, EntryPoint = "objc_msgSend")] + static extern IntPtr SendMessageWithParameter(IntPtr target, IntPtr selector, IntPtr param); + + [DllImport(ObjCRuntime)] + static extern IntPtr dlopen(string path, int mode); + + dlopen(AppKitFramework, 0x1); // have to invoke AppKit so that NSAlert doesn't return a null pointer + + IntPtr NSStringClass = GetClass("NSString"); + IntPtr Selector = GetSelector("stringWithUTF8String:"); + IntPtr SharedApp = SendMessage(GetClass("NSApplication"), GetSelector("sharedApplication")); + IntPtr NSAlert = SendMessage(GetClass("NSAlert"), GetSelector("alloc")); + IntPtr AlertInstance = SendMessage(NSAlert, GetSelector("init")); + + // Create caption, text, and button text. + IntPtr boxCaption = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi(caption)); + IntPtr boxText = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi(text)); + IntPtr boxButton = SendMessageWithParameter(NSStringClass, Selector, Marshal.StringToHGlobalAnsi(button)); + + // Set up the window. + SendMessageWithParameter(SharedApp, GetSelector("setActivationPolicy:"), IntPtr.Zero); // Give it a window. + SendMessageWithParameter(SharedApp, GetSelector("activateIgnoringOtherApps:"), (IntPtr) 1); // Force it to the front. + + // Set up the message box. + SendMessageWithParameter(AlertInstance, GetSelector("setAlertStyle:"), IntPtr.Zero); // Set style to warning. + SendMessageWithParameter(AlertInstance, GetSelector("setMessageText:"), boxCaption); + SendMessageWithParameter(AlertInstance, GetSelector("setInformativeText:"), boxText); + SendMessageWithParameter(AlertInstance, GetSelector("addButtonWithTitle:"), boxButton); + + // Send prompt to user, then clean up. + SendMessage(AlertInstance, GetSelector("runModal")); + SendMessage(AlertInstance, GetSelector("release")); + return 0; + } + } +} diff --git a/src/Ryujinx/UI/Helpers/LinuxSDLInterop.cs b/src/Ryujinx/UI/Helpers/LinuxSDLInterop.cs new file mode 100644 index 000000000..95885ba5c --- /dev/null +++ b/src/Ryujinx/UI/Helpers/LinuxSDLInterop.cs @@ -0,0 +1,30 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Ava.UI.Helpers +{ + public class LinuxSDLInterop + { + // TODO: add a parameter for prompt style + // TODO: look into adding text for the button + // TODO: check success of prompt box + public static int SimpleMessageBox(string caption, string text) + { + const string sdl = "SDL2"; + + [DllImport(sdl)] + static extern int SDL_Init(uint flags); + + [DllImport(sdl, CallingConvention = CallingConvention.Cdecl)] + static extern int SDL_ShowSimpleMessageBox(uint flags, string title, string message, IntPtr window); + + [DllImport(sdl)] + static extern void SDL_Quit(); + + SDL_Init(0); + SDL_ShowSimpleMessageBox(32 /* 32 = warning style */, caption, text, IntPtr.Zero); + SDL_Quit(); + return 0; + } + } +} From 9f363d63c21b074b5a1cb999b0ca603085e2cb5f Mon Sep 17 00:00:00 2001 From: Shyanne Date: Mon, 5 Jan 2026 15:58:55 -0500 Subject: [PATCH 10/12] Update Program.cs --- src/Ryujinx/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 8c9a190c5..c2018822a 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -180,7 +180,6 @@ namespace Ryujinx.Ava .UsePlatformDetect() .With(new X11PlatformOptions { - UseDBusMenu = false, UseDBusFilePicker = false, EnableMultiTouch = true, EnableIme = true, From 6d6ef44d28682db94bb04bf50d692bfe25ee4154 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Mon, 5 Jan 2026 16:15:31 -0500 Subject: [PATCH 11/12] Update macOSNativeInterop.cs --- src/Ryujinx/UI/Helpers/{Converters => }/macOSNativeInterop.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Ryujinx/UI/Helpers/{Converters => }/macOSNativeInterop.cs (100%) diff --git a/src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs b/src/Ryujinx/UI/Helpers/macOSNativeInterop.cs similarity index 100% rename from src/Ryujinx/UI/Helpers/Converters/macOSNativeInterop.cs rename to src/Ryujinx/UI/Helpers/macOSNativeInterop.cs From c3f7e1b47bd19e5e1812ed7c4d09047f5cba8d80 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Wed, 28 Jan 2026 00:27:53 -0500 Subject: [PATCH 12/12] Removed DBusFilePicker never should have been included tbh, i forgot to remove it lol --- src/Ryujinx/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index c2018822a..75c534b26 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -180,7 +180,6 @@ namespace Ryujinx.Ava .UsePlatformDetect() .With(new X11PlatformOptions { - UseDBusFilePicker = false, EnableMultiTouch = true, EnableIme = true, EnableInputFocusProxy = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP") == "gamescope",