mirror of https://github.com/PCSX2/pcsx2.git
FullscreenUI: Use native file selector on Flatpak
This commit is contained in:
parent
4d67f71217
commit
b9d7b63b32
|
@ -34,6 +34,7 @@
|
||||||
#include "pcsx2/Host.h"
|
#include "pcsx2/Host.h"
|
||||||
#include "pcsx2/INISettingsInterface.h"
|
#include "pcsx2/INISettingsInterface.h"
|
||||||
#include "pcsx2/ImGui/FullscreenUI.h"
|
#include "pcsx2/ImGui/FullscreenUI.h"
|
||||||
|
#include "pcsx2/ImGui/ImGuiFullscreen.h"
|
||||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||||
#include "pcsx2/Input/InputManager.h"
|
#include "pcsx2/Input/InputManager.h"
|
||||||
#include "pcsx2/MTGS.h"
|
#include "pcsx2/MTGS.h"
|
||||||
|
@ -272,7 +273,7 @@ void Host::BeginPresentFrame()
|
||||||
|
|
||||||
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
|
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
|
||||||
|
|
||||||
if(!idle_frame)
|
if (!idle_frame)
|
||||||
s_total_drawn_frames++;
|
s_total_drawn_frames++;
|
||||||
|
|
||||||
s_total_frames++;
|
s_total_frames++;
|
||||||
|
@ -399,6 +400,17 @@ void Host::OnCreateMemoryCardOpenRequested()
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Host::ShouldPreferHostFileSelector()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
||||||
|
FileSelectorFilters filters, std::string_view initial_directory)
|
||||||
|
{
|
||||||
|
callback(std::string());
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
|
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -538,7 +550,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||||
|
|
||||||
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks", true);
|
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks", true);
|
||||||
|
|
||||||
if(str.find("af") != std::string::npos)
|
if (str.find("af") != std::string::npos)
|
||||||
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks_AutoFlush", true);
|
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks_AutoFlush", true);
|
||||||
if (str.find("cpufb") != std::string::npos)
|
if (str.find("cpufb") != std::string::npos)
|
||||||
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks_CPU_FB_Conversion", true);
|
s_settings_interface.SetBoolValue("EmuCore/GS", "UserHacks_CPU_FB_Conversion", true);
|
||||||
|
@ -834,7 +846,7 @@ int wmain(int argc, wchar_t** argv)
|
||||||
u8_args.reserve(static_cast<size_t>(argc));
|
u8_args.reserve(static_cast<size_t>(argc));
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
|
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
|
||||||
|
|
||||||
std::vector<char*> u8_argptrs;
|
std::vector<char*> u8_argptrs;
|
||||||
u8_argptrs.reserve(u8_args.size());
|
u8_argptrs.reserve(u8_args.size());
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fmt\fmt\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fmt\fmt\include</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\include</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\imgui\include</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)pcsx2</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)pcsx2</AdditionalIncludeDirectories>
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "pcsx2/Host.h"
|
#include "pcsx2/Host.h"
|
||||||
#include "pcsx2/INISettingsInterface.h"
|
#include "pcsx2/INISettingsInterface.h"
|
||||||
#include "pcsx2/ImGui/FullscreenUI.h"
|
#include "pcsx2/ImGui/FullscreenUI.h"
|
||||||
|
#include "pcsx2/ImGui/ImGuiFullscreen.h"
|
||||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||||
#include "pcsx2/ImGui/ImGuiOverlays.h"
|
#include "pcsx2/ImGui/ImGuiOverlays.h"
|
||||||
#include "pcsx2/Input/InputManager.h"
|
#include "pcsx2/Input/InputManager.h"
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtWidgets/QMessageBox>
|
#include <QtWidgets/QMessageBox>
|
||||||
|
#include <QtWidgets/QFileDialog>
|
||||||
#include <QtGui/QClipboard>
|
#include <QtGui/QClipboard>
|
||||||
#include <QtGui/QInputMethod>
|
#include <QtGui/QInputMethod>
|
||||||
|
|
||||||
|
@ -1152,6 +1154,59 @@ void Host::OnCreateMemoryCardOpenRequested()
|
||||||
emit g_emu_thread->onCreateMemoryCardOpenRequested();
|
emit g_emu_thread->onCreateMemoryCardOpenRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Host::ShouldPreferHostFileSelector()
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
// If running inside a flatpak, we want to use native selectors/portals.
|
||||||
|
return (std::getenv("container") != nullptr);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
||||||
|
FileSelectorFilters filters, std::string_view initial_directory)
|
||||||
|
{
|
||||||
|
const bool from_cpu_thread = g_emu_thread->isOnEmuThread();
|
||||||
|
|
||||||
|
QString filters_str;
|
||||||
|
if (!filters.empty())
|
||||||
|
{
|
||||||
|
filters_str.append(QStringLiteral("All File Types (%1)")
|
||||||
|
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||||
|
for (const std::string& filter : filters)
|
||||||
|
{
|
||||||
|
filters_str.append(
|
||||||
|
QStringLiteral(";;%1 Files (%2)")
|
||||||
|
.arg(
|
||||||
|
QtUtils::StringViewToQString(std::string_view(filter).substr(filter.starts_with("*.") ? 2 : 0)).toUpper())
|
||||||
|
.arg(QString::fromStdString(filter)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QtHost::RunOnUIThread([title = QtUtils::StringViewToQString(title), select_directory, callback = std::move(callback),
|
||||||
|
filters_str = std::move(filters_str),
|
||||||
|
initial_directory = QtUtils::StringViewToQString(initial_directory),
|
||||||
|
from_cpu_thread]() mutable {
|
||||||
|
auto lock = g_main_window->pauseAndLockVM();
|
||||||
|
|
||||||
|
QString path;
|
||||||
|
|
||||||
|
if (select_directory)
|
||||||
|
path = QFileDialog::getExistingDirectory(lock.getDialogParent(), title, initial_directory);
|
||||||
|
else
|
||||||
|
path = QFileDialog::getOpenFileName(lock.getDialogParent(), title, initial_directory, filters_str);
|
||||||
|
|
||||||
|
if (!path.isEmpty())
|
||||||
|
path = QDir::toNativeSeparators(path);
|
||||||
|
|
||||||
|
if (from_cpu_thread)
|
||||||
|
Host::RunOnCPUThread([callback = std::move(callback), path = path.toStdString()]() { callback(path); });
|
||||||
|
else
|
||||||
|
callback(path.toStdString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Host::PumpMessagesOnCPUThread()
|
void Host::PumpMessagesOnCPUThread()
|
||||||
{
|
{
|
||||||
g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents);
|
g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents);
|
||||||
|
@ -1255,9 +1310,9 @@ bool QtHost::InitializeConfig()
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
nullptr, QStringLiteral("PCSX2"),
|
nullptr, QStringLiteral("PCSX2"),
|
||||||
QStringLiteral("Failed to create data directory at path\n\n%1\n\n"
|
QStringLiteral("Failed to create data directory at path\n\n%1\n\n"
|
||||||
"The error was: %2\n"
|
"The error was: %2\n"
|
||||||
"Please ensure this directory is writable. You can also try portable mode "
|
"Please ensure this directory is writable. You can also try portable mode "
|
||||||
"by creating portable.txt in the same directory you installed PCSX2 into.")
|
"by creating portable.txt in the same directory you installed PCSX2 into.")
|
||||||
.arg(QString::fromStdString(EmuFolders::DataRoot))
|
.arg(QString::fromStdString(EmuFolders::DataRoot))
|
||||||
.arg(QString::fromStdString(error.GetDescription())));
|
.arg(QString::fromStdString(error.GetDescription())));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
// SPDX-License-Identifier: LGPL-3.0+
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
#include "GS/Renderers/Common/GSTexture.h"
|
#include "GS/Renderers/Common/GSTexture.h"
|
||||||
#include "ImGui/ImGuiAnimated.h"
|
#include "ImGui/ImGuiAnimated.h"
|
||||||
#include "ImGui/ImGuiFullscreen.h"
|
#include "ImGui/ImGuiFullscreen.h"
|
||||||
|
#include "ImGui/ImGuiManager.h"
|
||||||
|
|
||||||
#include "common/Assertions.h"
|
#include "common/Assertions.h"
|
||||||
#include "common/Console.h"
|
#include "common/Console.h"
|
||||||
|
@ -1871,7 +1872,7 @@ void ImGuiFullscreen::PopulateFileSelectorItems()
|
||||||
{
|
{
|
||||||
if (s_file_selector_filters.empty() ||
|
if (s_file_selector_filters.empty() ||
|
||||||
std::none_of(s_file_selector_filters.begin(), s_file_selector_filters.end(),
|
std::none_of(s_file_selector_filters.begin(), s_file_selector_filters.end(),
|
||||||
[&fd](const std::string& filter) { return StringUtil::WildcardMatch(fd.FileName.c_str(), filter.c_str()); }))
|
[&fd](const std::string& filter) { return StringUtil::WildcardMatch(fd.FileName.c_str(), filter.c_str(), false); }))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1900,6 +1901,16 @@ bool ImGuiFullscreen::IsFileSelectorOpen()
|
||||||
void ImGuiFullscreen::OpenFileSelector(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
void ImGuiFullscreen::OpenFileSelector(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
||||||
FileSelectorFilters filters, std::string initial_directory)
|
FileSelectorFilters filters, std::string initial_directory)
|
||||||
{
|
{
|
||||||
|
if (initial_directory.empty() || !FileSystem::DirectoryExists(initial_directory.c_str()))
|
||||||
|
initial_directory = FileSystem::GetWorkingDirectory();
|
||||||
|
|
||||||
|
if (Host::ShouldPreferHostFileSelector())
|
||||||
|
{
|
||||||
|
Host::OpenHostFileSelectorAsync(ImGuiManager::StripIconCharacters(title), select_directory, std::move(callback),
|
||||||
|
std::move(filters), initial_directory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (s_file_selector_open)
|
if (s_file_selector_open)
|
||||||
CloseFileSelector();
|
CloseFileSelector();
|
||||||
|
|
||||||
|
@ -1909,8 +1920,6 @@ void ImGuiFullscreen::OpenFileSelector(std::string_view title, bool select_direc
|
||||||
s_file_selector_callback = std::move(callback);
|
s_file_selector_callback = std::move(callback);
|
||||||
s_file_selector_filters = std::move(filters);
|
s_file_selector_filters = std::move(filters);
|
||||||
|
|
||||||
if (initial_directory.empty() || !FileSystem::DirectoryExists(initial_directory.c_str()))
|
|
||||||
initial_directory = FileSystem::GetWorkingDirectory();
|
|
||||||
SetFileSelectorDirectory(std::move(initial_directory));
|
SetFileSelectorDirectory(std::move(initial_directory));
|
||||||
QueueResetFocus();
|
QueueResetFocus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,3 +264,17 @@ namespace ImGuiFullscreen
|
||||||
void GetFileSelectorHelpText(SmallStringBase& dest);
|
void GetFileSelectorHelpText(SmallStringBase& dest);
|
||||||
void GetInputDialogHelpText(SmallStringBase& dest);
|
void GetInputDialogHelpText(SmallStringBase& dest);
|
||||||
} // namespace ImGuiFullscreen
|
} // namespace ImGuiFullscreen
|
||||||
|
|
||||||
|
// Host UI triggers from Big Picture mode.
|
||||||
|
namespace Host
|
||||||
|
{
|
||||||
|
/// Returns true if native file dialogs should be preferred over Big Picture.
|
||||||
|
bool ShouldPreferHostFileSelector();
|
||||||
|
|
||||||
|
/// Opens a file selector dialog.
|
||||||
|
using FileSelectorCallback = std::function<void(const std::string& path)>;
|
||||||
|
using FileSelectorFilters = std::vector<std::string>;
|
||||||
|
void OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
||||||
|
FileSelectorFilters filters = FileSelectorFilters(),
|
||||||
|
std::string_view initial_directory = std::string_view());
|
||||||
|
} // namespace Host
|
||||||
|
|
|
@ -1061,3 +1061,25 @@ void ImGuiManager::SetSoftwareCursorPosition(u32 index, float pos_x, float pos_y
|
||||||
sc.pos.first = pos_x;
|
sc.pos.first = pos_x;
|
||||||
sc.pos.second = pos_y;
|
sc.pos.second = pos_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ImGuiManager::StripIconCharacters(std::string_view str)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.reserve(str.length());
|
||||||
|
|
||||||
|
for (size_t offset = 0; offset < str.length();)
|
||||||
|
{
|
||||||
|
char32_t utf;
|
||||||
|
offset += StringUtil::DecodeUTF8(str, offset, &utf);
|
||||||
|
|
||||||
|
// icon if outside BMP/SMP/TIP, or inside private use area
|
||||||
|
if (utf > 0x32FFF || (utf >= 0xE000 && utf <= 0xF8FF))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
StringUtil::EncodeAndAppendUTF8(result, utf);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringUtil::StripWhitespace(&result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -103,6 +103,9 @@ namespace ImGuiManager
|
||||||
|
|
||||||
/// Sets the position of a software cursor, used when we have relative coordinates such as controllers.
|
/// Sets the position of a software cursor, used when we have relative coordinates such as controllers.
|
||||||
void SetSoftwareCursorPosition(u32 index, float pos_x, float pos_y);
|
void SetSoftwareCursorPosition(u32 index, float pos_x, float pos_y);
|
||||||
|
|
||||||
|
/// Strips icon characters from a string.
|
||||||
|
std::string StripIconCharacters(std::string_view str);
|
||||||
} // namespace ImGuiManager
|
} // namespace ImGuiManager
|
||||||
|
|
||||||
namespace Host
|
namespace Host
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
// SPDX-License-Identifier: LGPL-3.0+
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
#include "pcsx2/Achievements.h"
|
#include "pcsx2/Achievements.h"
|
||||||
|
@ -6,6 +6,8 @@
|
||||||
#include "pcsx2/GameList.h"
|
#include "pcsx2/GameList.h"
|
||||||
#include "pcsx2/Host.h"
|
#include "pcsx2/Host.h"
|
||||||
#include "pcsx2/ImGui/FullscreenUI.h"
|
#include "pcsx2/ImGui/FullscreenUI.h"
|
||||||
|
#include "pcsx2/ImGui/ImGuiAnimated.h"
|
||||||
|
#include "pcsx2/ImGui/ImGuiFullscreen.h"
|
||||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||||
#include "pcsx2/Input/InputManager.h"
|
#include "pcsx2/Input/InputManager.h"
|
||||||
#include "pcsx2/VMManager.h"
|
#include "pcsx2/VMManager.h"
|
||||||
|
@ -213,6 +215,17 @@ void Host::OnCreateMemoryCardOpenRequested()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Host::ShouldPreferHostFileSelector()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
|
||||||
|
FileSelectorFilters filters, std::string_view initial_directory)
|
||||||
|
{
|
||||||
|
callback(std::string());
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
|
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
Loading…
Reference in New Issue