aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
diff options
context:
space:
mode:
authorIsaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>2024-02-11 02:09:18 +0000
committerGitHub <noreply@github.com>2024-02-11 03:09:18 +0100
commitf06d22d6f01e657ebbc0c8ef082739cd468e47b5 (patch)
treec10a566438d3801b33c1d7b4eff73ea62b2f1a63 /src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
parent84d6e8d121a1b329d26cc0e462aadd1108d99a04 (diff)
Infra: Capitalisation Consistency (#6296)1.1.1187
* Rename Ryujinx.UI.Common * Rename Ryujinx.UI.LocaleGenerator * Update in Files AboutWindow * Configuration State * Rename projects * Ryujinx/UI * Fix build * Main remaining inconsistencies * HLE.UI Namespace * HLE.UI Files * Namespace * Ryujinx.UI.Common.Configuration.UI * Ryujinx.UI.Common,Configuration.UI Files * More instances
Diffstat (limited to 'src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs')
-rw-r--r--src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
new file mode 100644
index 00000000..c2085b28
--- /dev/null
+++ b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs
@@ -0,0 +1,162 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using ShellLink;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.UI.Common.Helper
+{
+ public static class ShortcutHelper
+ {
+ [SupportedOSPlatform("windows")]
+ private static void CreateShortcutWindows(string applicationFilePath, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
+ {
+ string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
+ iconPath += ".ico";
+
+ MemoryStream iconDataStream = new(iconData);
+ var image = Image.Load(iconDataStream);
+ image.Mutate(x => x.Resize(128, 128));
+ SaveBitmapAsIcon(image, iconPath);
+
+ var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
+ shortcut.StringData.NameString = cleanedAppName;
+ shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
+ }
+
+ [SupportedOSPlatform("linux")]
+ private static void CreateShortcutLinux(string applicationFilePath, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
+ {
+ string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
+ var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop");
+ iconPath += ".png";
+
+ var image = Image.Load<Rgba32>(iconData);
+ image.SaveAsPng(iconPath);
+
+ using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
+ outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath)}");
+ }
+
+ [SupportedOSPlatform("macos")]
+ private static void CreateShortcutMacos(string appFilePath, byte[] iconData, string desktopPath, string cleanedAppName)
+ {
+ string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
+ var plistFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.plist");
+ var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-launch-script.sh");
+ // Macos .App folder
+ string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents");
+ string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS");
+
+ if (!Directory.Exists(scriptFolderPath))
+ {
+ Directory.CreateDirectory(scriptFolderPath);
+ }
+
+ // Runner script
+ const string ScriptName = "runner.sh";
+ string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
+ using StreamWriter scriptFile = new(scriptPath);
+
+ scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath));
+
+ // Set execute permission
+ FileInfo fileInfo = new(scriptPath);
+ fileInfo.UnixFileMode |= UnixFileMode.UserExecute;
+
+ // img
+ string resourceFolderPath = Path.Combine(contentFolderPath, "Resources");
+ if (!Directory.Exists(resourceFolderPath))
+ {
+ Directory.CreateDirectory(resourceFolderPath);
+ }
+
+ const string IconName = "icon.png";
+ var image = Image.Load<Rgba32>(iconData);
+ image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
+
+ // plist file
+ using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
+ outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
+ }
+
+ public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
+ {
+ string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
+ string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
+
+ if (OperatingSystem.IsWindows())
+ {
+ string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
+
+ CreateShortcutWindows(applicationFilePath, iconData, iconPath, cleanedAppName, desktopPath);
+
+ return;
+ }
+
+ if (OperatingSystem.IsLinux())
+ {
+ string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
+
+ Directory.CreateDirectory(iconPath);
+ CreateShortcutLinux(applicationFilePath, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
+
+ return;
+ }
+
+ if (OperatingSystem.IsMacOS())
+ {
+ CreateShortcutMacos(applicationFilePath, iconData, desktopPath, cleanedAppName);
+
+ return;
+ }
+
+ throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
+ }
+
+ private static string GetArgsString(string appFilePath)
+ {
+ // args are first defined as a list, for easier adjustments in the future
+ var argsList = new List<string>();
+
+ if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg))
+ {
+ argsList.Add("--root-data-dir");
+ argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
+ }
+
+ argsList.Add($"\"{appFilePath}\"");
+
+ return String.Join(" ", argsList);
+ }
+
+ /// <summary>
+ /// Creates a Icon (.ico) file using the source bitmap image at the specified file path.
+ /// </summary>
+ /// <param name="source">The source bitmap image that will be saved as an .ico file</param>
+ /// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
+ [SupportedOSPlatform("windows")]
+ private static void SaveBitmapAsIcon(Image source, string filePath)
+ {
+ // Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
+ byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
+ using FileStream fs = new(filePath, FileMode.Create);
+
+ fs.Write(header);
+ // Writing actual data
+ source.Save(fs, PngFormat.Instance);
+ // Getting data length (file length minus header)
+ long dataLength = fs.Length - header.Length;
+ // Write it in the correct place
+ fs.Seek(14, SeekOrigin.Begin);
+ fs.WriteByte((byte)dataLength);
+ fs.WriteByte((byte)(dataLength >> 8));
+ }
+ }
+}