Compare commits
2 Commits
android-10
...
android-99
Author | SHA1 | Date | |
---|---|---|---|
5b95f66146 | |||
019d648d4e |
@ -11,6 +11,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
|
|||||||
include(DownloadExternals)
|
include(DownloadExternals)
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
# Set bundled sdl2/qt as dependent options.
|
# Set bundled sdl2/qt as dependent options.
|
||||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||||
@ -98,8 +99,47 @@ if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
|||||||
DESTINATION "${vvl_lib_path}")
|
DESTINATION "${vvl_lib_path}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# On Android, fetch and compile libcxx before doing anything else
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set(CMAKE_SKIP_INSTALL_RULES ON)
|
set(CMAKE_SKIP_INSTALL_RULES ON)
|
||||||
|
set(LLVM_VERSION "15.0.6")
|
||||||
|
|
||||||
|
# Note: even though libcxx and libcxxabi have separate releases on the project page,
|
||||||
|
# the separated releases cannot be compiled. Only in-tree builds work. Therefore we
|
||||||
|
# must fetch the source release for the entire llvm tree.
|
||||||
|
FetchContent_Declare(llvm
|
||||||
|
URL "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-project-${LLVM_VERSION}.src.tar.xz"
|
||||||
|
URL_HASH SHA256=9d53ad04dc60cb7b30e810faf64c5ab8157dadef46c8766f67f286238256ff92
|
||||||
|
TLS_VERIFY TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(llvm)
|
||||||
|
|
||||||
|
# libcxx has support for most of the range library, but it's gated behind a flag:
|
||||||
|
add_compile_definitions(_LIBCPP_ENABLE_EXPERIMENTAL)
|
||||||
|
|
||||||
|
# Disable standard header inclusion
|
||||||
|
set(ANDROID_STL "none")
|
||||||
|
|
||||||
|
# libcxxabi
|
||||||
|
set(LIBCXXABI_INCLUDE_TESTS OFF)
|
||||||
|
set(LIBCXXABI_ENABLE_SHARED FALSE)
|
||||||
|
set(LIBCXXABI_ENABLE_STATIC TRUE)
|
||||||
|
set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXX_TARGET_INCLUDE_DIRECTORY}" CACHE STRING "" FORCE)
|
||||||
|
add_subdirectory("${llvm_SOURCE_DIR}/libcxxabi" "${llvm_BINARY_DIR}/libcxxabi")
|
||||||
|
link_libraries(cxxabi_static)
|
||||||
|
|
||||||
|
# libcxx
|
||||||
|
set(LIBCXX_ABI_NAMESPACE "__ndk1" CACHE STRING "" FORCE)
|
||||||
|
set(LIBCXX_CXX_ABI "libcxxabi")
|
||||||
|
set(LIBCXX_INCLUDE_TESTS OFF)
|
||||||
|
set(LIBCXX_INCLUDE_BENCHMARKS OFF)
|
||||||
|
set(LIBCXX_INCLUDE_DOCS OFF)
|
||||||
|
set(LIBCXX_ENABLE_SHARED FALSE)
|
||||||
|
set(LIBCXX_ENABLE_STATIC TRUE)
|
||||||
|
set(LIBCXX_ENABLE_ASSERTIONS FALSE)
|
||||||
|
add_subdirectory("${llvm_SOURCE_DIR}/libcxx" "${llvm_BINARY_DIR}/libcxx")
|
||||||
|
set_target_properties(cxx-headers PROPERTIES INTERFACE_COMPILE_OPTIONS "-isystem${CMAKE_BINARY_DIR}/${LIBCXX_INSTALL_INCLUDE_DIR}")
|
||||||
|
link_libraries(cxx_static cxx-headers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (YUZU_USE_BUNDLED_VCPKG)
|
if (YUZU_USE_BUNDLED_VCPKG)
|
||||||
@ -289,7 +329,7 @@ find_package(Boost 1.79.0 REQUIRED context)
|
|||||||
find_package(enet 1.3 MODULE)
|
find_package(enet 1.3 MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 9 REQUIRED)
|
||||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
find_package(LLVM 17 MODULE COMPONENTS Demangle)
|
||||||
find_package(lz4 REQUIRED)
|
find_package(lz4 REQUIRED)
|
||||||
find_package(nlohmann_json 3.8 REQUIRED)
|
find_package(nlohmann_json 3.8 REQUIRED)
|
||||||
find_package(Opus 1.3 MODULE)
|
find_package(Opus 1.3 MODULE)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
|
| [11649](https://github.com/yuzu-emu/yuzu//pull/11649) | [`a5fb9de6f`](https://github.com/yuzu-emu/yuzu//pull/11649/files) | android: Driver manager | [t895](https://github.com/t895/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
@ -27,7 +27,7 @@ android {
|
|||||||
namespace = "org.yuzu.yuzu_emu"
|
namespace = "org.yuzu.yuzu_emu"
|
||||||
|
|
||||||
compileSdkVersion = "android-34"
|
compileSdkVersion = "android-34"
|
||||||
ndkVersion = "26.1.10909125"
|
ndkVersion = "25.2.9519653"
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
@ -203,23 +203,23 @@ ktlint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.12.0")
|
implementation("androidx.core:core-ktx:1.10.1")
|
||||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.3.1")
|
implementation("androidx.recyclerview:recyclerview:1.3.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.fragment:fragment-ktx:1.6.1")
|
implementation("androidx.fragment:fragment-ktx:1.6.0")
|
||||||
implementation("androidx.documentfile:documentfile:1.0.1")
|
implementation("androidx.documentfile:documentfile:1.0.1")
|
||||||
implementation("com.google.android.material:material:1.9.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
implementation("androidx.preference:preference:1.2.0")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||||
implementation("io.coil-kt:coil:2.2.2")
|
implementation("io.coil-kt:coil:2.2.2")
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.window:window:1.2.0-beta03")
|
implementation("androidx.window:window:1.2.0-beta03")
|
||||||
implementation("org.ini4j:ini4j:0.5.4")
|
implementation("org.ini4j:ini4j:0.5.4")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
|
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
android:localeConfig="@xml/locales_config"
|
android:localeConfig="@xml/locales_config"
|
||||||
android:banner="@drawable/tv_banner"
|
android:banner="@drawable/tv_banner"
|
||||||
|
android:extractNativeLibs="true"
|
||||||
android:fullBackupContent="@xml/data_extraction_rules"
|
android:fullBackupContent="@xml/data_extraction_rules"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
||||||
android:enableOnBackInvokedCallback="true">
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
@ -26,7 +26,6 @@ import org.yuzu.yuzu_emu.model.DriverViewModel
|
|||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class DriverManagerFragment : Fragment() {
|
class DriverManagerFragment : Fragment() {
|
||||||
@ -155,29 +154,29 @@ class DriverManagerFragment : Fragment() {
|
|||||||
R.string.installing_driver,
|
R.string.installing_driver,
|
||||||
false
|
false
|
||||||
) {
|
) {
|
||||||
val driverPath =
|
|
||||||
"${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}"
|
|
||||||
val driverFile = File(driverPath)
|
|
||||||
|
|
||||||
// Ignore file exceptions when a user selects an invalid zip
|
// Ignore file exceptions when a user selects an invalid zip
|
||||||
try {
|
try {
|
||||||
if (!GpuDriverHelper.copyDriverToInternalStorage(result)) {
|
GpuDriverHelper.copyDriverToInternalStorage(result)
|
||||||
throw IOException("Driver failed validation!")
|
|
||||||
}
|
|
||||||
} catch (_: IOException) {
|
} catch (_: IOException) {
|
||||||
if (driverFile.exists()) {
|
|
||||||
driverFile.delete()
|
|
||||||
}
|
|
||||||
return@newInstance getString(R.string.select_gpu_driver_error)
|
return@newInstance getString(R.string.select_gpu_driver_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
val driverData = GpuDriverHelper.getMetadataFromZip(driverFile)
|
val driverData = GpuDriverHelper.customDriverData
|
||||||
|
if (driverData.name == null) {
|
||||||
|
return@newInstance getString(R.string.select_gpu_driver_error)
|
||||||
|
}
|
||||||
|
|
||||||
val driverInList =
|
val driverInList =
|
||||||
driverViewModel.driverList.value.firstOrNull { it.second == driverData }
|
driverViewModel.driverList.value.firstOrNull { it.second == driverData }
|
||||||
if (driverInList != null) {
|
if (driverInList != null) {
|
||||||
return@newInstance getString(R.string.driver_already_installed)
|
return@newInstance getString(R.string.driver_already_installed)
|
||||||
} else {
|
} else {
|
||||||
driverViewModel.addDriver(Pair(driverPath, driverData))
|
driverViewModel.addDriver(
|
||||||
|
Pair(
|
||||||
|
"${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}",
|
||||||
|
driverData
|
||||||
|
)
|
||||||
|
)
|
||||||
driverViewModel.setNewDriverInstalled(true)
|
driverViewModel.setNewDriverInstalled(true)
|
||||||
}
|
}
|
||||||
return@newInstance Any()
|
return@newInstance Any()
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.1.2" apply false
|
id("com.android.application") version "8.0.2" apply false
|
||||||
id("com.android.library") version "8.1.2" apply false
|
id("com.android.library") version "8.0.2" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.21" apply false
|
id("org.jetbrains.kotlin.android") version "1.8.21" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,13 +15,12 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <stop_token>
|
#include <stop_token>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
template <typename Condvar, typename Lock, typename Pred>
|
template <typename Condvar, typename Lock, typename Pred>
|
||||||
void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) {
|
void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) {
|
||||||
cv.wait(lk, token, std::forward<Pred>(pred));
|
cv.wait(lk, token, std::move(pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Rep, typename Period>
|
template <typename Rep, typename Period>
|
||||||
@ -110,7 +109,7 @@ public:
|
|||||||
|
|
||||||
// Insert the callback.
|
// Insert the callback.
|
||||||
stop_state_callback ret = ++m_next_callback;
|
stop_state_callback ret = ++m_next_callback;
|
||||||
m_callbacks.emplace(ret, std::move(f));
|
m_callbacks.emplace(ret, move(f));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +162,7 @@ private:
|
|||||||
friend class stop_source;
|
friend class stop_source;
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
friend class stop_callback;
|
friend class stop_callback;
|
||||||
stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(std::move(stop_state)) {}
|
stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||||
@ -199,7 +198,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class jthread;
|
friend class jthread;
|
||||||
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
|
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
|
||||||
: m_stop_state(std::move(stop_state)) {}
|
: m_stop_state(move(stop_state)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||||
@ -219,16 +218,16 @@ public:
|
|||||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||||
: m_stop_state(st.m_stop_state) {
|
: m_stop_state(st.m_stop_state) {
|
||||||
if (m_stop_state) {
|
if (m_stop_state) {
|
||||||
m_callback = m_stop_state->insert_callback(std::move(cb));
|
m_callback = m_stop_state->insert_callback(move(cb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename C>
|
template <typename C>
|
||||||
requires constructible_from<Callback, C>
|
requires constructible_from<Callback, C>
|
||||||
explicit stop_callback(stop_token&& st,
|
explicit stop_callback(stop_token&& st,
|
||||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||||
: m_stop_state(std::move(st.m_stop_state)) {
|
: m_stop_state(move(st.m_stop_state)) {
|
||||||
if (m_stop_state) {
|
if (m_stop_state) {
|
||||||
m_callback = m_stop_state->insert_callback(std::move(cb));
|
m_callback = m_stop_state->insert_callback(move(cb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~stop_callback() {
|
~stop_callback() {
|
||||||
@ -261,7 +260,7 @@ public:
|
|||||||
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
|
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
|
||||||
explicit jthread(F&& f, Args&&... args)
|
explicit jthread(F&& f, Args&&... args)
|
||||||
: m_stop_state(make_shared<polyfill::stop_state>()),
|
: m_stop_state(make_shared<polyfill::stop_state>()),
|
||||||
m_thread(make_thread(std::forward<F>(f), std::forward<Args>(args)...)) {}
|
m_thread(make_thread(move(f), move(args)...)) {}
|
||||||
|
|
||||||
~jthread() {
|
~jthread() {
|
||||||
if (joinable()) {
|
if (joinable()) {
|
||||||
@ -318,9 +317,9 @@ private:
|
|||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
thread make_thread(F&& f, Args&&... args) {
|
thread make_thread(F&& f, Args&&... args) {
|
||||||
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
|
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
|
||||||
return thread(std::forward<F>(f), get_stop_token(), std::forward<Args>(args)...);
|
return thread(move(f), get_stop_token(), move(args)...);
|
||||||
} else {
|
} else {
|
||||||
return thread(std::forward<F>(f), std::forward<Args>(args)...);
|
return thread(move(f), move(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3405,11 +3405,6 @@ Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* out_K
|
|||||||
new_attr, KMemoryBlockDisableMergeAttribute::Locked,
|
new_attr, KMemoryBlockDisableMergeAttribute::Locked,
|
||||||
KMemoryBlockDisableMergeAttribute::None);
|
KMemoryBlockDisableMergeAttribute::None);
|
||||||
|
|
||||||
// If we have an output page group, open.
|
|
||||||
if (out_pg) {
|
|
||||||
out_pg->Open();
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,13 +826,12 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
|
|||||||
tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size);
|
tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size);
|
||||||
tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
|
tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
|
||||||
|
|
||||||
// Before deleting rows, cancel the worker so that it is not using them
|
|
||||||
emit ShouldCancelWorker();
|
|
||||||
|
|
||||||
// Delete any rows that might already exist if we're repopulating
|
// Delete any rows that might already exist if we're repopulating
|
||||||
item_model->removeRows(0, item_model->rowCount());
|
item_model->removeRows(0, item_model->rowCount());
|
||||||
search_field->clear();
|
search_field->clear();
|
||||||
|
|
||||||
|
emit ShouldCancelWorker();
|
||||||
|
|
||||||
GameListWorker* worker =
|
GameListWorker* worker =
|
||||||
new GameListWorker(vfs, provider, game_dirs, compatibility_list, play_time_manager, system);
|
new GameListWorker(vfs, provider, game_dirs, compatibility_list, play_time_manager, system);
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
|||||||
void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, bool deep_scan,
|
void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, bool deep_scan,
|
||||||
GameListDir* parent_dir) {
|
GameListDir* parent_dir) {
|
||||||
const auto callback = [this, target, parent_dir](const std::filesystem::path& path) -> bool {
|
const auto callback = [this, target, parent_dir](const std::filesystem::path& path) -> bool {
|
||||||
if (stop_requested) {
|
if (stop_processing) {
|
||||||
// Breaks the callback loop.
|
// Breaks the callback loop.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -399,6 +399,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameListWorker::run() {
|
void GameListWorker::run() {
|
||||||
|
stop_processing = false;
|
||||||
provider->ClearAllEntries();
|
provider->ClearAllEntries();
|
||||||
|
|
||||||
for (UISettings::GameDir& game_dir : game_dirs) {
|
for (UISettings::GameDir& game_dir : game_dirs) {
|
||||||
@ -426,11 +427,9 @@ void GameListWorker::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit Finished(watch_list);
|
emit Finished(watch_list);
|
||||||
processing_completed.Set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameListWorker::Cancel() {
|
void GameListWorker::Cancel() {
|
||||||
this->disconnect();
|
this->disconnect();
|
||||||
stop_requested.store(true);
|
stop_processing = true;
|
||||||
processing_completed.Wait();
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "common/thread.h"
|
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/play_time_manager.h"
|
#include "yuzu/play_time_manager.h"
|
||||||
|
|
||||||
@ -83,9 +82,7 @@ private:
|
|||||||
const PlayTime::PlayTimeManager& play_time_manager;
|
const PlayTime::PlayTimeManager& play_time_manager;
|
||||||
|
|
||||||
QStringList watch_list;
|
QStringList watch_list;
|
||||||
|
std::atomic_bool stop_processing;
|
||||||
Common::Event processing_completed;
|
|
||||||
std::atomic_bool stop_requested = false;
|
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
@ -67,7 +67,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
|||||||
#define QT_NO_OPENGL
|
#define QT_NO_OPENGL
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
@ -77,7 +76,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
|||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
@ -2871,50 +2869,44 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
|
|||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
|
||||||
std::filesystem::path target_directory{};
|
std::filesystem::path target_directory{};
|
||||||
|
// Determine target directory for shortcut
|
||||||
|
#if defined(WIN32)
|
||||||
|
const char* home = std::getenv("USERPROFILE");
|
||||||
|
#else
|
||||||
|
const char* home = std::getenv("HOME");
|
||||||
|
#endif
|
||||||
|
const std::filesystem::path home_path = (home == nullptr ? "~" : home);
|
||||||
|
const char* xdg_data_home = std::getenv("XDG_DATA_HOME");
|
||||||
|
|
||||||
switch (target) {
|
if (target == GameListShortcutTarget::Desktop) {
|
||||||
case GameListShortcutTarget::Desktop: {
|
target_directory = home_path / "Desktop";
|
||||||
const QString desktop_path =
|
if (!Common::FS::IsDir(target_directory)) {
|
||||||
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
QMessageBox::critical(
|
||||||
target_directory = desktop_path.toUtf8().toStdString();
|
this, tr("Create Shortcut"),
|
||||||
break;
|
tr("Cannot create shortcut on desktop. Path \"%1\" does not exist.")
|
||||||
}
|
.arg(QString::fromStdString(target_directory.generic_string())),
|
||||||
case GameListShortcutTarget::Applications: {
|
QMessageBox::StandardButton::Ok);
|
||||||
const QString applications_path =
|
return;
|
||||||
QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
|
}
|
||||||
if (applications_path.isEmpty()) {
|
} else if (target == GameListShortcutTarget::Applications) {
|
||||||
const char* home = std::getenv("HOME");
|
target_directory = (xdg_data_home == nullptr ? home_path / ".local/share" : xdg_data_home) /
|
||||||
if (home != nullptr) {
|
"applications";
|
||||||
target_directory = std::filesystem::path(home) / ".local/share/applications";
|
if (!Common::FS::CreateDirs(target_directory)) {
|
||||||
}
|
QMessageBox::critical(
|
||||||
} else {
|
this, tr("Create Shortcut"),
|
||||||
target_directory = applications_path.toUtf8().toStdString();
|
tr("Cannot create shortcut in applications menu. Path \"%1\" "
|
||||||
|
"does not exist and cannot be created.")
|
||||||
|
.arg(QString::fromStdString(target_directory.generic_string())),
|
||||||
|
QMessageBox::StandardButton::Ok);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QDir dir(QString::fromStdString(target_directory.generic_string()));
|
|
||||||
if (!dir.exists()) {
|
|
||||||
QMessageBox::critical(this, tr("Create Shortcut"),
|
|
||||||
tr("Cannot create shortcut. Path \"%1\" does not exist.")
|
|
||||||
.arg(QString::fromStdString(target_directory.generic_string())),
|
|
||||||
QMessageBox::StandardButton::Ok);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string game_file_name = std::filesystem::path(game_path).filename().string();
|
const std::string game_file_name = std::filesystem::path(game_path).filename().string();
|
||||||
// Determine full paths for icon and shortcut
|
// Determine full paths for icon and shortcut
|
||||||
#if defined(__linux__) || defined(__FreeBSD__)
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
const char* home = std::getenv("HOME");
|
|
||||||
const std::filesystem::path home_path = (home == nullptr ? "~" : home);
|
|
||||||
const char* xdg_data_home = std::getenv("XDG_DATA_HOME");
|
|
||||||
|
|
||||||
std::filesystem::path system_icons_path =
|
std::filesystem::path system_icons_path =
|
||||||
(xdg_data_home == nullptr ? home_path / ".local/share/"
|
(xdg_data_home == nullptr ? home_path / ".local/share/" : xdg_data_home) /
|
||||||
: std::filesystem::path(xdg_data_home)) /
|
|
||||||
"icons/hicolor/256x256";
|
"icons/hicolor/256x256";
|
||||||
if (!Common::FS::CreateDirs(system_icons_path)) {
|
if (!Common::FS::CreateDirs(system_icons_path)) {
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
|
Reference in New Issue
Block a user