mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +00:00
Qt: Deprecate processEvents() part 2
This commit is contained in:
parent
191e132c6c
commit
378a69ea85
@ -475,7 +475,7 @@ namespace fs
|
||||
dir() = default;
|
||||
|
||||
// Open dir handle
|
||||
explicit dir(const std::string& path)
|
||||
explicit dir(const std::string& path) noexcept
|
||||
{
|
||||
open(path);
|
||||
}
|
||||
@ -484,7 +484,7 @@ namespace fs
|
||||
bool open(const std::string& path);
|
||||
|
||||
// Check whether the handle is valid (opened directory)
|
||||
explicit operator bool() const
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return m_dir.operator bool();
|
||||
}
|
||||
@ -531,7 +531,7 @@ namespace fs
|
||||
from_current
|
||||
};
|
||||
|
||||
iterator(const dir* parent, mode mode_ = mode::from_first)
|
||||
iterator(const dir* parent, mode mode_ = mode::from_first) noexcept
|
||||
: m_parent(parent)
|
||||
{
|
||||
if (!m_parent)
|
||||
@ -569,6 +569,13 @@ namespace fs
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator old = *this;
|
||||
*this = {m_parent, mode::from_current};
|
||||
return old;
|
||||
}
|
||||
|
||||
bool operator !=(const iterator& rhs) const
|
||||
{
|
||||
return m_parent != rhs.m_parent;
|
||||
|
@ -2840,18 +2840,32 @@ void Emulator::Resume()
|
||||
|
||||
u64 get_sysutil_cb_manager_read_count();
|
||||
|
||||
void process_qt_events();
|
||||
void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op);
|
||||
|
||||
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savestate)
|
||||
{
|
||||
const auto old_state = m_state.load();
|
||||
// Ensure no game has booted inbetween
|
||||
const auto guard = Emu.MakeEmulationStateGuard();
|
||||
|
||||
stop_counter_t old_emu_id{};
|
||||
system_state old_state{};
|
||||
|
||||
// Perform atomic load of both
|
||||
do
|
||||
{
|
||||
old_emu_id = GetEmulationIdentifier();
|
||||
old_state = m_state.load();
|
||||
}
|
||||
while (old_emu_id != GetEmulationIdentifier() || old_state != m_state.load());
|
||||
|
||||
if (old_state == system_state::stopped || old_state == system_state::stopping)
|
||||
{
|
||||
while (!async_op && m_state != system_state::stopped)
|
||||
if (!async_op && old_state == system_state::stopping)
|
||||
{
|
||||
process_qt_events();
|
||||
std::this_thread::sleep_for(16ms);
|
||||
qt_events_aware_op(5, [&]()
|
||||
{
|
||||
return old_emu_id != GetEmulationIdentifier() || m_state != system_state::stopping;
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2859,10 +2873,12 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
|
||||
if (!savestate && m_emu_state_close_pending)
|
||||
{
|
||||
while (!async_op && m_state != system_state::stopped)
|
||||
if (!async_op)
|
||||
{
|
||||
process_qt_events();
|
||||
std::this_thread::sleep_for(16ms);
|
||||
qt_events_aware_op(5, [&]()
|
||||
{
|
||||
return old_emu_id != GetEmulationIdentifier() || m_state != system_state::stopping;
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2880,10 +2896,12 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
// The callback has been rudely ignored, we have no other option but to force termination
|
||||
Kill(allow_autoexit && !savestate, savestate);
|
||||
|
||||
while (!async_op && m_state != system_state::stopped)
|
||||
if (!async_op)
|
||||
{
|
||||
process_qt_events();
|
||||
std::this_thread::sleep_for(16ms);
|
||||
qt_events_aware_op(5, [&]()
|
||||
{
|
||||
return (old_emu_id != GetEmulationIdentifier() || m_state == system_state::stopped);
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2893,9 +2911,14 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
{
|
||||
bool read_sysutil_signal = false;
|
||||
|
||||
for (u32 i = 100; i < 140; i++)
|
||||
u32 i = 100;
|
||||
|
||||
qt_events_aware_op(50, [&]()
|
||||
{
|
||||
std::this_thread::sleep_for(50ms);
|
||||
if (i >= 140)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Prevent pausing by other threads while in this loop
|
||||
CallFromMainThread([this]()
|
||||
@ -2903,8 +2926,6 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
Resume();
|
||||
}, nullptr, true, read_counter);
|
||||
|
||||
process_qt_events(); // Is nullified when performed on non-main thread
|
||||
|
||||
if (!read_sysutil_signal && read_counter != get_sysutil_cb_manager_read_count())
|
||||
{
|
||||
i -= 100; // Grant 5 seconds (if signal is not read force kill after two second)
|
||||
@ -2913,9 +2934,13 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
|
||||
if (static_cast<u64>(info) != m_stop_ctr)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process events
|
||||
i++;
|
||||
return false;
|
||||
});
|
||||
|
||||
// An inevitable attempt to terminate the *current* emulation course will be issued after 7s
|
||||
CallFromMainThread([allow_autoexit, this]()
|
||||
@ -2932,11 +2957,10 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
{
|
||||
perform_kill();
|
||||
|
||||
while (m_state != system_state::stopped)
|
||||
qt_events_aware_op(5, [&]()
|
||||
{
|
||||
process_qt_events();
|
||||
std::this_thread::sleep_for(16ms);
|
||||
}
|
||||
return (old_emu_id != GetEmulationIdentifier() || m_state == system_state::stopped);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -3932,25 +3956,37 @@ u32 Emulator::AddGamesFromDir(const std::string& path)
|
||||
games_added++;
|
||||
}
|
||||
|
||||
process_qt_events();
|
||||
fs::dir fs_dir{path};
|
||||
|
||||
// search direct subdirectories, that way we can drop one folder containing all games
|
||||
for (auto&& dir_entry : fs::dir(path))
|
||||
auto path_it = fs_dir.begin();
|
||||
|
||||
qt_events_aware_op(0, [&]()
|
||||
{
|
||||
if (!dir_entry.is_directory || dir_entry.name == "." || dir_entry.name == "..")
|
||||
// search direct subdirectories, that way we can drop one folder containing all games
|
||||
for (; path_it != fs_dir.end(); ++path_it)
|
||||
{
|
||||
continue;
|
||||
auto dir_entry = std::move(*path_it);
|
||||
|
||||
if (!dir_entry.is_directory || dir_entry.name == "." || dir_entry.name == "..")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string dir_path = path + '/' + dir_entry.name;
|
||||
|
||||
if (const game_boot_result error = AddGame(dir_path); error == game_boot_result::no_errors)
|
||||
{
|
||||
games_added++;
|
||||
}
|
||||
|
||||
// Process events
|
||||
++path_it;
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string dir_path = path + '/' + dir_entry.name;
|
||||
|
||||
if (const game_boot_result error = AddGame(dir_path); error == game_boot_result::no_errors)
|
||||
{
|
||||
games_added++;
|
||||
}
|
||||
|
||||
process_qt_events();
|
||||
}
|
||||
// Exit loop
|
||||
return true;
|
||||
});
|
||||
|
||||
m_games_config.set_save_on_dirty(true);
|
||||
|
||||
|
@ -54,6 +54,8 @@ namespace rsx::overlays
|
||||
extern void reset_debug_overlay();
|
||||
}
|
||||
|
||||
extern void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op);
|
||||
|
||||
/** Emu.Init() wrapper for user management */
|
||||
void main_application::InitializeEmulator(const std::string& user, bool show_gui)
|
||||
{
|
||||
@ -182,8 +184,8 @@ EmuCallbacks main_application::CreateCallbacks()
|
||||
callbacks.init_pad_handler = [this](std::string_view title_id)
|
||||
{
|
||||
ensure(g_fxo->init<named_thread<pad_thread>>(get_thread(), m_game_window, title_id));
|
||||
extern void process_qt_events();
|
||||
while (!pad::g_started) process_qt_events();
|
||||
|
||||
qt_events_aware_op(0, [](){ return !!pad::g_started; });
|
||||
};
|
||||
|
||||
callbacks.get_audio = []() -> std::shared_ptr<AudioBackend>
|
||||
|
@ -577,12 +577,10 @@ void gui_application::InitializeCallbacks()
|
||||
|
||||
callbacks.on_missing_fw = [this]()
|
||||
{
|
||||
if (!m_main_window)
|
||||
if (m_main_window)
|
||||
{
|
||||
return;
|
||||
m_main_window->OnMissingFw();
|
||||
}
|
||||
|
||||
m_main_window->OnMissingFw();
|
||||
};
|
||||
|
||||
callbacks.handle_taskbar_progress = [this](s32 type, s32 value)
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
extern void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op);
|
||||
|
||||
namespace gui
|
||||
{
|
||||
QString stylesheet;
|
||||
@ -193,11 +195,18 @@ void gui_settings::ShowInfoBox(const QString& title, const QString& text, const
|
||||
|
||||
bool gui_settings::GetBootConfirmation(QWidget* parent, const gui_save& gui_save_entry)
|
||||
{
|
||||
while (Emu.GetStatus(false) == system_state::stopping)
|
||||
auto info = Emu.GetEmulationIdentifier();
|
||||
|
||||
qt_events_aware_op(16, [&]()
|
||||
{
|
||||
QCoreApplication::processEvents();
|
||||
std::this_thread::sleep_for(16ms);
|
||||
}
|
||||
if (Emu.GetStatus(false) != system_state::stopping)
|
||||
{
|
||||
ensure(info == Emu.GetEmulationIdentifier());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
|
@ -82,6 +82,9 @@
|
||||
|
||||
#include "ui_main_window.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
|
||||
#if QT_CONFIG(permissions)
|
||||
#include <QGuiApplication>
|
||||
#include <QPermissions>
|
||||
@ -96,15 +99,63 @@ std::shared_ptr<CPUDisAsm> make_basic_ppu_disasm();
|
||||
|
||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
|
||||
extern void process_qt_events()
|
||||
extern void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op)
|
||||
{
|
||||
ensure(wrapped_op);
|
||||
|
||||
if (thread_ctrl::is_main())
|
||||
{
|
||||
// NOTE:
|
||||
// I noticed that calling this from an Emu callback can cause the
|
||||
// caller to get stuck for a while during newly opened Qt dialogs.
|
||||
// Adding a timeout here doesn't seem to do anything in that case.
|
||||
QApplication::processEvents();
|
||||
QEventLoop* event_loop = nullptr;
|
||||
|
||||
std::shared_ptr<std::function<void()>> check_iteration;
|
||||
check_iteration = std::make_shared<std::function<void()>>([&]()
|
||||
{
|
||||
if (wrapped_op())
|
||||
{
|
||||
event_loop->exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTimer::singleShot(repeat_duration_ms, *check_iteration);
|
||||
}
|
||||
});
|
||||
|
||||
while (!wrapped_op())
|
||||
{
|
||||
// Init event loop
|
||||
event_loop = new QEventLoop();
|
||||
|
||||
// Queue event initially
|
||||
QTimer::singleShot(0, *check_iteration);
|
||||
|
||||
// Event loop
|
||||
event_loop->exec();
|
||||
|
||||
// Cleanup
|
||||
event_loop->deleteLater();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!wrapped_op())
|
||||
{
|
||||
if (repeat_duration_ms == 0)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
else if (thread_ctrl::get_current())
|
||||
{
|
||||
thread_ctrl::wait_for(repeat_duration_ms * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(repeat_duration_ms));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1066,9 +1117,16 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo
|
||||
pdlg.show();
|
||||
|
||||
// Wait for the completion
|
||||
for (usz i = 0, set_text = umax; i < readers.size() && result.error == package_install_result::error_type::no_error;)
|
||||
int reader_it = 0;
|
||||
int set_text = -1;
|
||||
|
||||
qt_events_aware_op(5, [&, readers_size = ::narrow<int>(readers.size())]()
|
||||
{
|
||||
std::this_thread::sleep_for(5ms);
|
||||
if (reader_it == readers_size || result.error != package_install_result::error_type::no_error)
|
||||
{
|
||||
// Exit loop
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pdlg.wasCanceled())
|
||||
{
|
||||
@ -1079,26 +1137,28 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo
|
||||
reader.abort_extract();
|
||||
}
|
||||
|
||||
break;
|
||||
// Exit loop
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update progress window
|
||||
const int progress = readers[i].get_progress(pdlg.maximum());
|
||||
const int progress = readers[reader_it].get_progress(pdlg.maximum());
|
||||
pdlg.SetValue(progress);
|
||||
|
||||
if (set_text != i)
|
||||
if (set_text != reader_it)
|
||||
{
|
||||
pdlg.setLabelText(tr("Installing package (%0/%1), please wait...\n\n%2").arg(i + 1).arg(readers.size()).arg(get_app_info(packages[i])));
|
||||
set_text = i;
|
||||
pdlg.setLabelText(tr("Installing package (%0/%1), please wait...\n\n%2").arg(reader_it + 1).arg(readers_size).arg(get_app_info(packages[reader_it])));
|
||||
set_text = reader_it;
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
if (progress == pdlg.maximum())
|
||||
{
|
||||
i++;
|
||||
reader_it++;
|
||||
}
|
||||
}
|
||||
|
||||
// Process events
|
||||
return false;
|
||||
});
|
||||
|
||||
const bool success = worker();
|
||||
|
||||
@ -1350,13 +1410,19 @@ void main_window::ExtractTar()
|
||||
|
||||
QString error;
|
||||
|
||||
for (const QString& file : files)
|
||||
auto files_it = files.begin();
|
||||
int pdlg_progress = 0;
|
||||
|
||||
qt_events_aware_op(0, [&]()
|
||||
{
|
||||
if (pdlg.wasCanceled())
|
||||
if (pdlg.wasCanceled() || files_it == files.end())
|
||||
{
|
||||
break;
|
||||
// Exit loop
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString& file = *files_it;
|
||||
|
||||
// Do not abort on failure here, in case the user selected a wrong file in multi-selection while the rest are valid
|
||||
if (!extract_tar(sstr(file), sstr(dir) + '/'))
|
||||
{
|
||||
@ -1369,9 +1435,12 @@ void main_window::ExtractTar()
|
||||
error += file;
|
||||
}
|
||||
|
||||
pdlg.SetValue(pdlg.value() + 1);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
pdlg_progress++;
|
||||
pdlg.SetValue(pdlg_progress);
|
||||
|
||||
files_it++;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!error.isEmpty())
|
||||
{
|
||||
@ -1629,18 +1698,25 @@ void main_window::HandlePupInstallation(const QString& file_path, const QString&
|
||||
});
|
||||
|
||||
// Wait for the completion
|
||||
for (uint value = progress.load(); value < update_filenames.size(); std::this_thread::sleep_for(5ms), value = progress)
|
||||
qt_events_aware_op(5, [&]()
|
||||
{
|
||||
const uint value = progress.load();
|
||||
|
||||
if (value >= update_filenames.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pdlg.wasCanceled())
|
||||
{
|
||||
progress = -1;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update progress window
|
||||
pdlg.SetValue(static_cast<int>(value));
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Join thread
|
||||
worker();
|
||||
|
@ -24,6 +24,8 @@ static constexpr int radius_range = 1000;
|
||||
static const constexpr f64 min_radius_conversion = radius_range / g_cfg_move.min_radius.max;
|
||||
static const constexpr f64 max_radius_conversion = radius_range / g_cfg_move.max_radius.max;
|
||||
|
||||
extern void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op);
|
||||
|
||||
ps_move_tracker_dialog::ps_move_tracker_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ps_move_tracker_dialog)
|
||||
@ -232,7 +234,7 @@ ps_move_tracker_dialog::ps_move_tracker_dialog(QWidget* parent)
|
||||
reset_camera();
|
||||
|
||||
m_input_thread = std::make_unique<named_thread<pad_thread>>(thread(), window(), "");
|
||||
while (!pad::g_started) QApplication::processEvents();
|
||||
qt_events_aware_op(0, [](){ return !!pad::g_started; });
|
||||
|
||||
adjustSize();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user