diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/fs/path_util.cpp | 10 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 158 | ||||
| -rw-r--r-- | src/yuzu/main.h | 2 |
3 files changed, 79 insertions, 91 deletions
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 3d88fcf4f..bcd64156e 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -254,11 +254,8 @@ fs::path GetExeDirectory() { | |||
| 254 | WCHAR exe_path[MAX_PATH]; | 254 | WCHAR exe_path[MAX_PATH]; |
| 255 | 255 | ||
| 256 | if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) { | 256 | if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) { |
| 257 | std::wstring wideExePath(exe_path); | 257 | std::wstring wide_exe_path(exe_path); |
| 258 | 258 | return fs::path{Common::UTF16ToUTF8(wide_exe_path)}.parent_path(); | |
| 259 | // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with | ||
| 260 | // the Windows library (Filesystem converts the strings literally). | ||
| 261 | return fs::path{Common::UTF16ToUTF8(wideExePath)}.parent_path(); | ||
| 262 | } else { | 259 | } else { |
| 263 | LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current " | 260 | LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current " |
| 264 | "process"); | 261 | "process"); |
| @@ -273,9 +270,6 @@ fs::path GetAppDataRoamingDirectory() { | |||
| 273 | if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) { | 270 | if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) { |
| 274 | std::wstring wideAppdataRoamingPath(appdata_roaming_path); | 271 | std::wstring wideAppdataRoamingPath(appdata_roaming_path); |
| 275 | CoTaskMemFree(appdata_roaming_path); | 272 | CoTaskMemFree(appdata_roaming_path); |
| 276 | |||
| 277 | // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with | ||
| 278 | // the Windows library (Filesystem converts the strings literally). | ||
| 279 | return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)}; | 273 | return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)}; |
| 280 | } else { | 274 | } else { |
| 281 | LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory"); | 275 | LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory"); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f2b91a7f3..36f9551a1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2847,8 +2847,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2847 | const std::string& arguments, const std::string& categories, | 2847 | const std::string& arguments, const std::string& categories, |
| 2848 | const std::string& keywords, const std::string& name) { | 2848 | const std::string& keywords, const std::string& name) { |
| 2849 | 2849 | ||
| 2850 | bool shortcut_succeeded = false; | ||
| 2851 | |||
| 2852 | // Copy characters if they are not illegal in Windows filenames | 2850 | // Copy characters if they are not illegal in Windows filenames |
| 2853 | std::string filename = ""; | 2851 | std::string filename = ""; |
| 2854 | const std::string illegal_chars = "<>:\"/\\|?*"; | 2852 | const std::string illegal_chars = "<>:\"/\\|?*"; |
| @@ -2858,22 +2856,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2858 | 2856 | ||
| 2859 | if (filename.empty()) { | 2857 | if (filename.empty()) { |
| 2860 | LOG_ERROR(Frontend, "Filename is empty"); | 2858 | LOG_ERROR(Frontend, "Filename is empty"); |
| 2861 | shortcut_succeeded = false; | 2859 | return false; |
| 2862 | return shortcut_succeeded; | ||
| 2863 | } | 2860 | } |
| 2864 | 2861 | ||
| 2865 | // Replace characters that are illegal in Windows filenames | 2862 | // Append .desktop or .lnk extension |
| 2866 | std::filesystem::path shortcut_path_full = shortcut_path / filename; | 2863 | std::filesystem::path shortcut_path_full = shortcut_path / filename; |
| 2867 | 2864 | ||
| 2868 | #if defined(__linux__) || defined(__FreeBSD__) | 2865 | #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD |
| 2869 | shortcut_path_full += ".desktop"; | ||
| 2870 | #elif defined(_WIN32) | ||
| 2871 | shortcut_path_full += ".lnk"; | ||
| 2872 | #endif | ||
| 2873 | |||
| 2874 | LOG_ERROR(Frontend, "Create shortcut path: {}", shortcut_path_full.string()); | ||
| 2875 | |||
| 2876 | #if defined(__linux__) || defined(__FreeBSD__) | ||
| 2877 | // This desktop file template was writing referencing | 2866 | // This desktop file template was writing referencing |
| 2878 | // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html | 2867 | // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html |
| 2879 | try { | 2868 | try { |
| @@ -2881,9 +2870,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2881 | // Plus 'Type' is required | 2870 | // Plus 'Type' is required |
| 2882 | if (name.empty()) { | 2871 | if (name.empty()) { |
| 2883 | LOG_ERROR(Frontend, "Name is empty"); | 2872 | LOG_ERROR(Frontend, "Name is empty"); |
| 2884 | shortcut_succeeded = false; | 2873 | return false; |
| 2885 | return shortcut_succeeded; | ||
| 2886 | } | 2874 | } |
| 2875 | |||
| 2876 | // Append .desktop extension | ||
| 2877 | shortcut_path_full += ".desktop"; | ||
| 2878 | |||
| 2879 | // Create shortcut file | ||
| 2887 | std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); | 2880 | std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); |
| 2888 | 2881 | ||
| 2889 | if (shortcut_stream.is_open()) { | 2882 | if (shortcut_stream.is_open()) { |
| @@ -2923,78 +2916,82 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2923 | 2916 | ||
| 2924 | } else { | 2917 | } else { |
| 2925 | LOG_ERROR(Frontend, "Failed to create shortcut"); | 2918 | LOG_ERROR(Frontend, "Failed to create shortcut"); |
| 2926 | return false; | ||
| 2927 | } | 2919 | } |
| 2928 | 2920 | ||
| 2929 | shortcut_stream.close(); | 2921 | shortcut_stream.close(); |
| 2930 | } catch (const std::exception& e) { | 2922 | } catch (const std::exception& e) { |
| 2931 | LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); | 2923 | LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); |
| 2932 | } | 2924 | } |
| 2933 | #elif defined(_WIN32) | 2925 | return false; |
| 2934 | // Initialize COM | 2926 | #elif defined(_WIN32) // Windows |
| 2935 | auto hr = CoInitialize(NULL); | 2927 | HRESULT hr = CoInitialize(NULL); |
| 2936 | if (FAILED(hr)) { | 2928 | if (SUCCEEDED(hr)) { |
| 2937 | return shortcut_succeeded; | ||
| 2938 | } | ||
| 2939 | 2929 | ||
| 2940 | IShellLinkW* ps1; | 2930 | IShellLinkW* ps1 = nullptr; |
| 2931 | IPersistFile* persist_file = nullptr; | ||
| 2941 | 2932 | ||
| 2942 | auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, | 2933 | SCOPE_EXIT({ |
| 2943 | (void**)&ps1); | 2934 | if (persist_file != nullptr) { |
| 2935 | persist_file->Release(); | ||
| 2936 | } | ||
| 2937 | if (ps1 != nullptr) { | ||
| 2938 | ps1->Release(); | ||
| 2939 | } | ||
| 2944 | 2940 | ||
| 2945 | // The UTF-16 / UTF-8 conversion is broken in C++, it is necessary to perform these steps and | 2941 | CoUninitialize(); |
| 2946 | // resort to the native Windows function. | 2942 | }); |
| 2947 | std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); | ||
| 2948 | std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); | ||
| 2949 | std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); | ||
| 2950 | std::wstring warguments = Common::UTF8ToUTF16W(arguments); | ||
| 2951 | std::wstring wcomment = Common::UTF8ToUTF16W(comment); | ||
| 2952 | 2943 | ||
| 2953 | if (SUCCEEDED(hres)) { | 2944 | HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
| 2954 | if (std::filesystem::is_regular_file(command)) | 2945 | IID_IShellLinkW, (void**)&ps1); |
| 2955 | hres = ps1->SetPath(wcommand.data()); | ||
| 2956 | 2946 | ||
| 2957 | if (SUCCEEDED(hres) && !arguments.empty()) | 2947 | std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); |
| 2958 | hres = ps1->SetArguments(warguments.data()); | 2948 | std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); |
| 2949 | std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); | ||
| 2950 | std::wstring warguments = Common::UTF8ToUTF16W(arguments); | ||
| 2951 | std::wstring wcomment = Common::UTF8ToUTF16W(comment); | ||
| 2952 | |||
| 2953 | if (SUCCEEDED(hres)) { | ||
| 2954 | if (std::filesystem::is_regular_file(command)) { | ||
| 2955 | hres = ps1->SetPath(wcommand.data()); | ||
| 2956 | } else { | ||
| 2957 | LOG_ERROR(Frontend, "Command is not a regular file"); | ||
| 2958 | return false; | ||
| 2959 | } | ||
| 2959 | 2960 | ||
| 2960 | if (SUCCEEDED(hres) && !comment.empty()) | 2961 | if (SUCCEEDED(hres) && !arguments.empty()) { |
| 2961 | hres = ps1->SetDescription(wcomment.data()); | 2962 | hres = ps1->SetArguments(warguments.data()); |
| 2963 | } | ||
| 2962 | 2964 | ||
| 2963 | if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) | 2965 | if (SUCCEEDED(hres) && !comment.empty()) { |
| 2964 | hres = ps1->SetIconLocation(wicon_path.data(), 0); | 2966 | hres = ps1->SetDescription(wcomment.data()); |
| 2967 | } | ||
| 2965 | 2968 | ||
| 2966 | IPersistFile* pPersistFile = nullptr; | 2969 | if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { |
| 2970 | hres = ps1->SetIconLocation(wicon_path.data(), 0); | ||
| 2971 | } | ||
| 2967 | 2972 | ||
| 2968 | if (SUCCEEDED(hres)) { | 2973 | if (SUCCEEDED(hres)) { |
| 2969 | hres = ps1->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); | 2974 | hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); |
| 2975 | } | ||
| 2970 | 2976 | ||
| 2971 | if (SUCCEEDED(hres) && pPersistFile != nullptr) { | 2977 | if (SUCCEEDED(hres) && persist_file != nullptr) { |
| 2972 | hres = pPersistFile->Save(wshortcut_path_full.data(), TRUE); | 2978 | // Append .lnk extension and save shortcut |
| 2979 | shortcut_path_full += ".lnk"; | ||
| 2980 | hres = persist_file->Save(wshortcut_path_full.data(), TRUE); | ||
| 2973 | if (SUCCEEDED(hres)) { | 2981 | if (SUCCEEDED(hres)) { |
| 2974 | shortcut_succeeded = true; | 2982 | return true; |
| 2983 | } else { | ||
| 2984 | LOG_ERROR(Frontend, "Failed to create shortcut"); | ||
| 2975 | } | 2985 | } |
| 2976 | } | 2986 | } |
| 2987 | } else { | ||
| 2988 | LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); | ||
| 2977 | } | 2989 | } |
| 2978 | |||
| 2979 | if (pPersistFile != nullptr) { | ||
| 2980 | pPersistFile->Release(); | ||
| 2981 | } | ||
| 2982 | } else { | ||
| 2983 | LOG_ERROR(Frontend, "Failed to create IShellLinkWinstance"); | ||
| 2984 | } | 2990 | } |
| 2985 | 2991 | return false; | |
| 2986 | ps1->Release(); | 2992 | #else // Unsupported platform |
| 2987 | CoUninitialize(); | 2993 | return false; |
| 2988 | #endif | 2994 | #endif |
| 2989 | |||
| 2990 | if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) { | ||
| 2991 | LOG_ERROR(Frontend, "Shortcut created"); | ||
| 2992 | } else { | ||
| 2993 | LOG_ERROR(Frontend, "Shortcut error, failed to create it"); | ||
| 2994 | shortcut_succeeded = false; | ||
| 2995 | } | ||
| 2996 | |||
| 2997 | return shortcut_succeeded; | ||
| 2998 | } | 2995 | } |
| 2999 | 2996 | ||
| 3000 | // Messages in pre-defined message boxes for less code spaghetti | 2997 | // Messages in pre-defined message boxes for less code spaghetti |
| @@ -3049,31 +3046,31 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, | |||
| 3049 | } | 3046 | } |
| 3050 | 3047 | ||
| 3051 | bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, | 3048 | bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, |
| 3052 | std::filesystem::path& icons_path) { | 3049 | std::filesystem::path& out_icon_path) { |
| 3053 | 3050 | ||
| 3054 | // Get path to Yuzu icons directory & icon extension | 3051 | // Get path to Yuzu icons directory & icon extension |
| 3055 | std::string ico_extension = "png"; | 3052 | std::string ico_extension = "png"; |
| 3056 | #if defined(_WIN32) | 3053 | #if defined(_WIN32) |
| 3057 | icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; | 3054 | out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; |
| 3058 | ico_extension = "ico"; | 3055 | ico_extension = "ico"; |
| 3059 | #elif defined(__linux__) || defined(__FreeBSD__) | 3056 | #elif defined(__linux__) || defined(__FreeBSD__) |
| 3060 | icons_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; | 3057 | out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; |
| 3061 | #endif | 3058 | #endif |
| 3062 | 3059 | ||
| 3063 | // Create icons directory if it doesn't exist | 3060 | // Create icons directory if it doesn't exist |
| 3064 | if (!Common::FS::CreateDirs(icons_path)) { | 3061 | if (!Common::FS::CreateDirs(out_icon_path)) { |
| 3065 | QMessageBox::critical( | 3062 | QMessageBox::critical( |
| 3066 | this, tr("Create Icon"), | 3063 | this, tr("Create Icon"), |
| 3067 | tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") | 3064 | tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") |
| 3068 | .arg(QString::fromStdString(icons_path.string())), | 3065 | .arg(QString::fromStdString(out_icon_path.string())), |
| 3069 | QMessageBox::StandardButton::Ok); | 3066 | QMessageBox::StandardButton::Ok); |
| 3070 | icons_path = ""; // Reset path | 3067 | out_icon_path = ""; // Reset path |
| 3071 | return false; | 3068 | return false; |
| 3072 | } | 3069 | } |
| 3073 | 3070 | ||
| 3074 | // Create icon file path | 3071 | // Create icon file path |
| 3075 | icons_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) | 3072 | out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) |
| 3076 | : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); | 3073 | : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); |
| 3077 | return true; | 3074 | return true; |
| 3078 | } | 3075 | } |
| 3079 | 3076 | ||
| @@ -3096,13 +3093,11 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3096 | QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); | 3093 | QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); |
| 3097 | } else if (target == GameListShortcutTarget::Applications) { | 3094 | } else if (target == GameListShortcutTarget::Applications) { |
| 3098 | #if defined(_WIN32) | 3095 | #if defined(_WIN32) |
| 3099 | HANDLE hProcess = GetCurrentProcess(); | ||
| 3100 | if (!IsUserAnAdmin()) { | 3096 | if (!IsUserAnAdmin()) { |
| 3101 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, | 3097 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, |
| 3102 | ""); | 3098 | ""); |
| 3103 | return; | 3099 | return; |
| 3104 | } | 3100 | } |
| 3105 | CloseHandle(hProcess); | ||
| 3106 | #endif // _WIN32 | 3101 | #endif // _WIN32 |
| 3107 | shortcut_path = | 3102 | shortcut_path = |
| 3108 | QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); | 3103 | QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); |
| @@ -3110,9 +3105,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3110 | 3105 | ||
| 3111 | // Icon path and title | 3106 | // Icon path and title |
| 3112 | std::string title; | 3107 | std::string title; |
| 3113 | std::filesystem::path icons_path; | 3108 | std::filesystem::path out_icon_path; |
| 3114 | if (std::filesystem::exists(shortcut_path)) { | 3109 | if (std::filesystem::exists(shortcut_path)) { |
| 3115 | |||
| 3116 | // Get title from game file | 3110 | // Get title from game file |
| 3117 | const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), | 3111 | const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), |
| 3118 | system->GetContentProvider()}; | 3112 | system->GetContentProvider()}; |
| @@ -3139,8 +3133,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3139 | QImage icon_data = | 3133 | QImage icon_data = |
| 3140 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); | 3134 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); |
| 3141 | 3135 | ||
| 3142 | if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) { | 3136 | if (GMainWindow::MakeShortcutIcoPath(program_id, title, out_icon_path)) { |
| 3143 | if (!SaveIconToFile(icons_path, icon_data)) { | 3137 | if (!SaveIconToFile(out_icon_path, icon_data)) { |
| 3144 | LOG_ERROR(Frontend, "Could not write icon to file"); | 3138 | LOG_ERROR(Frontend, "Could not write icon to file"); |
| 3145 | } | 3139 | } |
| 3146 | } | 3140 | } |
| @@ -3178,8 +3172,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3178 | const std::string categories = "Game;Emulator;Qt;"; | 3172 | const std::string categories = "Game;Emulator;Qt;"; |
| 3179 | const std::string keywords = "Switch;Nintendo;"; | 3173 | const std::string keywords = "Switch;Nintendo;"; |
| 3180 | 3174 | ||
| 3181 | if (GMainWindow::CreateShortcutLink(shortcut_path, comment, icons_path, yuzu_command, arguments, | 3175 | if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command, |
| 3182 | categories, keywords, title)) { | 3176 | arguments, categories, keywords, title)) { |
| 3183 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, | 3177 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, |
| 3184 | title); | 3178 | title); |
| 3185 | return; | 3179 | return; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d7426607f..d3a1bf5b9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -444,7 +444,7 @@ private: | |||
| 444 | QString GetTasStateDescription() const; | 444 | QString GetTasStateDescription() const; |
| 445 | bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title); | 445 | bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title); |
| 446 | bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, | 446 | bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, |
| 447 | std::filesystem::path& icons_path); | 447 | std::filesystem::path& out_icon_path); |
| 448 | bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, | 448 | bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, |
| 449 | const std::filesystem::path& icon_path, | 449 | const std::filesystem::path& icon_path, |
| 450 | const std::filesystem::path& command, const std::string& arguments, | 450 | const std::filesystem::path& command, const std::string& arguments, |