summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp4
-rw-r--r--src/mainwindow.cpp2
-rw-r--r--src/modinfodialogconflicts.cpp2
-rw-r--r--src/organizercore.cpp2
-rw-r--r--src/organizerproxy.cpp6
-rw-r--r--src/processrunner.cpp155
-rw-r--r--src/processrunner.h43
7 files changed, 107 insertions, 107 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 2b9a2f4d..02347ee3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -634,7 +634,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
try {
organizer.processRunner()
.setFromShortcut(shortcut)
- .setWaitForCompletion(ProcessRunner::NoRefresh)
+ .setWaitForCompletion()
.run();
return 0;
@@ -662,7 +662,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
// pass the remaining parameters to the binary
organizer.processRunner()
.setFromFileOrExecutable(exeName, arguments)
- .setWaitForCompletion(ProcessRunner::NoRefresh)
+ .setWaitForCompletion()
.run();
return 0;
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index d304f8b7..c2d91bcc 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -5404,7 +5404,7 @@ void MainWindow::openDataFile()
m_OrganizerCore.processRunner()
.setFromFile(this, targetInfo)
- .setWaitForCompletion(ProcessRunner::NoRefresh)
+ .setWaitForCompletion()
.run();
}
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index 8aefd4c6..d37f068c 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -529,7 +529,7 @@ void ConflictsTab::openItems(QTreeView* tree)
for_each_in_selection(tree, [&](const ConflictItem* item) {
core().processRunner()
.setFromFile(parentWidget(), item->fileName())
- .setWaitForCompletion(ProcessRunner::NoRefresh)
+ .setWaitForCompletion()
.run();
return true;
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 943750ed..96ae84a8 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -357,7 +357,7 @@ void OrganizerCore::externalMessage(const QString &message)
if(moshortcut.hasExecutable()) {
processRunner()
.setFromShortcut(moshortcut)
- .setWaitForCompletion(ProcessRunner::NoRefresh)
+ .setWaitForCompletion()
.run();
}
}
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index 0b6f8df1..420e2d82 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -128,7 +128,9 @@ HANDLE OrganizerProxy::startApplication(
.setFromFileOrExecutable(exe, args, cwd, profile, overwrite, ignoreOverwrite)
.run();
- return runner.processHandle();
+ // the plugin is in charge of closing the handle, unless waitForApplication()
+ // is called on it
+ return runner.stealProcessHandle().release();
}
bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
@@ -142,7 +144,7 @@ bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
auto runner = m_Proxied->processRunner();
const auto r = runner
- .setWaitForCompletion(ProcessRunner::NoRefresh, LockWidget::OutputRequired)
+ .setWaitForCompletion(ProcessRunner::ForceWait, LockWidget::OutputRequired)
.attachToProcess(handle);
if (exitCode) {
diff --git a/src/processrunner.cpp b/src/processrunner.cpp
index b732204c..9cc2ce52 100644
--- a/src/processrunner.cpp
+++ b/src/processrunner.cpp
@@ -368,8 +368,8 @@ void SpawnedProcess::destroy()
ProcessRunner::ProcessRunner(OrganizerCore& core, IUserInterface* ui) :
- m_core(core), m_ui(ui), m_lock(LockWidget::NoReason), m_refresh(NoRefresh),
- m_handle(INVALID_HANDLE_VALUE), m_exitCode(-1)
+ m_core(core), m_ui(ui), m_lockReason(LockWidget::NoReason),
+ m_waitFlags(NoFlags), m_handle(INVALID_HANDLE_VALUE), m_exitCode(-1)
{
m_sp.hooked = true;
}
@@ -417,10 +417,10 @@ ProcessRunner& ProcessRunner::setProfileName(const QString& profileName)
}
ProcessRunner& ProcessRunner::setWaitForCompletion(
- RefreshModes refresh, LockWidget::Reasons reason)
+ WaitFlags flags, LockWidget::Reasons reason)
{
- m_refresh = refresh;
- m_lock = reason;
+ m_waitFlags = flags;
+ m_lockReason = reason;
return *this;
}
@@ -593,13 +593,13 @@ ProcessRunner::Results ProcessRunner::run()
return Error;
}
- m_handle = r.stealProcessHandle();
+ m_handle.reset(r.stealProcessHandle());
// not all files will return a valid handle even if opening them was
// successful, such as inproc handlers (like the photo viewer); in this
// case it's impossible to determine the status, so just say it's still
// running
- if (m_handle == INVALID_HANDLE_VALUE) {
+ if (m_handle.get() == INVALID_HANDLE_VALUE) {
return Running;
}
} else {
@@ -642,8 +642,8 @@ ProcessRunner::Results ProcessRunner::run()
adjustForVirtualized(game, m_sp, settings);
- m_handle = startBinary(parent, m_sp);
- if (m_handle == INVALID_HANDLE_VALUE) {
+ m_handle.reset(startBinary(parent, m_sp));
+ if (m_handle.get() == INVALID_HANDLE_VALUE) {
return Error;
}
}
@@ -653,14 +653,46 @@ ProcessRunner::Results ProcessRunner::run()
ProcessRunner::Results ProcessRunner::postRun()
{
- if (m_lock == LockWidget::NoReason) {
- return Running;
+ const bool mustWait = (m_waitFlags & ForceWait);
+
+ if (mustWait && m_lockReason == LockWidget::NoReason) {
+ // never lock the ui without an escape hatch for the user
+ log::debug(
+ "the ForceWait flag is set but the lock reason wasn't, "
+ "defaulting to LockUI");
+
+ m_lockReason = LockWidget::LockUI;
+ }
+
+ if (mustWait) {
+ if (!Settings::instance().interface().lockGUI()) {
+ // at least tell the user what's going on
+ log::debug(
+ "locking is disabled, but the output of the application is required; "
+ "overriding this setting and locking the ui");
+ }
+ } else {
+ // no force wait
+
+ if (m_lockReason == LockWidget::NoReason) {
+ // no locking requested
+ return Running;
+ }
+
+ if (!Settings::instance().interface().lockGUI()) {
+ // disabling locking is like clicking on unlock immediately
+ log::debug("not waiting for process because locking is disabled");
+ return ForceUnlocked;
+ }
}
- const auto r = waitForProcessCompletionWithLock(
- m_handle, &m_exitCode, m_lock);
+ auto r = Error;
+
+ withLock([&](auto& lock) {
+ r = waitForProcess(m_handle.get(), &m_exitCode, lock);
+ });
- if (r == Completed && m_refresh == Refresh) {
+ if (r == Completed && (m_waitFlags & Refresh)) {
m_core.afterRun(m_sp.binary, m_exitCode);
}
@@ -669,101 +701,64 @@ ProcessRunner::Results ProcessRunner::postRun()
ProcessRunner::Results ProcessRunner::attachToProcess(HANDLE h)
{
- m_handle = h;
+ m_handle.reset(h);
return postRun();
}
-DWORD ProcessRunner::exitCode()
+DWORD ProcessRunner::exitCode() const
{
return m_exitCode;
}
-HANDLE ProcessRunner::processHandle()
+HANDLE ProcessRunner::getProcessHandle() const
{
- return m_handle;
+ return m_handle.get();
}
-
-void ProcessRunner::withLock(
- LockWidget::Reasons reason, std::function<void (LockWidget&)> f)
+env::HandlePtr ProcessRunner::stealProcessHandle()
{
- auto lock = std::make_unique<LockWidget>(
- m_ui ? m_ui->qtWidget() : nullptr, reason);
-
- f(*lock);
+ return std::move(m_handle);
}
-ProcessRunner::Results ProcessRunner::waitForProcessCompletionWithLock(
- HANDLE handle, LPDWORD exitCode, LockWidget::Reasons reason)
+ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock(
+ LockWidget::Reasons reason)
{
+ m_lockReason = reason;
+
if (!Settings::instance().interface().lockGUI()) {
- log::debug("not waiting for process because user has disabled locking");
+ // disabling locking is like clicking on unlock immediately
return ForceUnlocked;
}
- return waitForApplication(handle, exitCode, reason);
-}
-
-ProcessRunner::Results ProcessRunner::waitForApplication(
- HANDLE handle, LPDWORD exitCode, LockWidget::Reasons reason)
-{
- // don't check for lockGUI() setting; this _always_ locks the ui and waits
- // for completion
- //
- // this is typically called only from:
- // 1) OrganizerProxy, which allows plugins to wait on applications until
- // they're finished
- //
- // the check_fnis plugin for example will start FNIS, wait for it to
- // complete, and then check the exit code; this has to work regardless of
- // the locking setting;
- //
- // 2) waitForProcessCompletionWithLock() above, which has already checked the
- // lock setting
-
auto r = Error;
- withLock(reason, [&](auto& lock) {
- r = waitForProcess(handle, exitCode, lock);
- });
+ withLock([&](auto& lock) {
+ for (;;) {
+ const auto processes = getRunningUSVFSProcesses();
+ if (processes.empty()) {
+ break;
+ }
- return r;
-}
+ r = waitForProcesses(processes, lock);
-ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock(
- LockWidget::Reasons reason)
-{
- if (!Settings::instance().interface().lockGUI()) {
- log::debug("not waiting for usvfs processes because user has disabled locking");
- return ForceUnlocked;
- }
+ if (r != Completed) {
+ // error, cancelled, or unlocked
+ return;
+ }
- auto r = Error;
+ // this process is completed, check for others
+ }
- withLock(reason, [&](auto& lock) {
- r = waitForAllUSVFSProcesses(lock);
+ r = Completed;
});
return r;
}
-ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcesses(LockWidget& lock)
+void ProcessRunner::withLock(std::function<void (LockWidget&)> f)
{
- for (;;) {
- const auto processes = getRunningUSVFSProcesses();
- if (processes.empty()) {
- break;
- }
-
- const auto r = waitForProcesses(processes, lock);
-
- if (r != Completed) {
- // error, cancelled, or unlocked
- return r;
- }
-
- // this process is completed, check for others
- }
+ auto lk = std::make_unique<LockWidget>(
+ m_ui ? m_ui->qtWidget() : nullptr, m_lockReason);
- return Completed;
+ f(*lk);
}
diff --git a/src/processrunner.h b/src/processrunner.h
index 62ec7a9e..41c0f12c 100644
--- a/src/processrunner.h
+++ b/src/processrunner.h
@@ -3,6 +3,7 @@
#include "spawn.h"
#include "lockwidget.h"
+#include "envmodule.h"
#include <executableinfo.h>
class OrganizerCore;
@@ -44,16 +45,25 @@ public:
ForceUnlocked
};
- enum RefreshModes
+ enum WaitFlag
{
- NoRefresh = 1,
- Refresh
+ NoFlags = 0x00,
+ Refresh = 0x01,
+ ForceWait = 0x02
};
+ using WaitFlags = QFlags<WaitFlag>;
+
using ForcedLibraries = QList<MOBase::ExecutableForcedLoadSetting>;
ProcessRunner(OrganizerCore& core, IUserInterface* ui);
+ // move only
+ ProcessRunner(ProcessRunner&&) = default;
+ ProcessRunner& operator=(const ProcessRunner&) = delete;
+ ProcessRunner(const ProcessRunner&) = delete;
+ ProcessRunner& operator=(ProcessRunner&&) = delete;
+
ProcessRunner& setBinary(const QFileInfo &binary);
ProcessRunner& setArguments(const QString& arguments);
ProcessRunner& setCurrentDirectory(const QDir& directory);
@@ -62,7 +72,7 @@ public:
ProcessRunner& setForcedLibraries(const ForcedLibraries& forcedLibraries);
ProcessRunner& setProfileName(const QString& profileName);
ProcessRunner& setWaitForCompletion(
- RefreshModes refresh, LockWidget::Reasons reason=LockWidget::LockUI);
+ WaitFlags flags=NoFlags, LockWidget::Reasons reason=LockWidget::LockUI);
ProcessRunner& setFromFile(QWidget* parent, const QFileInfo& targetInfo);
ProcessRunner& setFromExecutable(const Executable& exe);
@@ -79,8 +89,9 @@ public:
Results run();
Results attachToProcess(HANDLE h);
- DWORD exitCode();
- HANDLE processHandle();
+ DWORD exitCode() const;
+ HANDLE getProcessHandle() const;
+ env::HandlePtr stealProcessHandle();
Results waitForAllUSVFSProcessesWithLock(LockWidget::Reasons reason);
@@ -91,24 +102,16 @@ private:
QString m_customOverwrite;
ForcedLibraries m_forcedLibraries;
QString m_profileName;
- LockWidget::Reasons m_lock;
- RefreshModes m_refresh;
+ LockWidget::Reasons m_lockReason;
+ WaitFlags m_waitFlags;
QString m_shellOpen;
- HANDLE m_handle;
+ env::HandlePtr m_handle;
DWORD m_exitCode;
Results postRun();
-
- void withLock(
- LockWidget::Reasons reason, std::function<void (LockWidget&)> f);
-
- Results waitForProcessCompletionWithLock(
- HANDLE handle, LPDWORD exitCode, LockWidget::Reasons reason);
-
- Results waitForApplication(
- HANDLE processHandle, LPDWORD exitCode, LockWidget::Reasons reason);
-
- Results waitForAllUSVFSProcesses(LockWidget& lock);
+ void withLock(std::function<void (LockWidget&)> f);
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ProcessRunner::WaitFlags);
+
#endif // PROCESSRUNNER_H