From dcf88361d49da262acaac335d1317a5d7ef42ded Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 15 Dec 2019 21:54:27 -0500 Subject: don't display the overlay on dialog boxes handle non-modal windows too fixed crash when closing an overlayed dialog --- src/uilocker.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 14 deletions(-) (limited to 'src/uilocker.cpp') diff --git a/src/uilocker.cpp b/src/uilocker.cpp index 8c4e0c2c..af9b9b96 100644 --- a/src/uilocker.cpp +++ b/src/uilocker.cpp @@ -20,6 +20,9 @@ public: ~UILockerInterface() { + if (m_topLevel) { + delete m_topLevel.data(); + } } void checkTarget() @@ -31,14 +34,8 @@ public: bool set() { - QWidget* newTarget = nullptr; - - newTarget = m_mainUI; - if (auto* w = QApplication::activeModalWidget()) { - newTarget = w; - } - - if (newTarget == m_target) { + QWidget* newTarget = findTarget(); + if (m_topLevel && newTarget == m_target) { return false; } @@ -98,8 +95,8 @@ public: QWidget* topLevel() { - return m_topLevel.get(); - } + return m_topLevel.data(); + } private: class Filter : public QObject @@ -129,7 +126,7 @@ private: std::unique_ptr m_timer; QWidget* m_mainUI; QWidget* m_target; - std::unique_ptr m_topLevel; + QPointer m_topLevel; QLabel* m_message; QLabel* m_info; QStringList m_labels; @@ -143,6 +140,55 @@ private: return (m_target != nullptr); } + QWidget* findTarget() + { + auto isValidTarget = [](QWidget* w) { + // skip message boxes + if (dynamic_cast(w)) { + return false; + } + + // skip invisible widgets + if (!w->isVisible()) { + return false; + } + + // skip windows that are too small + if (w->height() < 150) { + return false; + } + + return true; + }; + + + // find a modal dialog + QWidget* w = QApplication::activeModalWidget(); + + while (w && w != m_mainUI) { + if (isValidTarget(w)) { + return w; + } + + w = w->parentWidget(); + } + + // find a non-modal dialog that's a child of the main window + if (m_mainUI) { + const auto topLevels = QApplication::topLevelWidgets(); + + for (auto* w : topLevels) { + if (w && w->parentWidget() == m_mainUI) { + if (isValidTarget(w)) { + return w; + } + } + } + } + + return m_mainUI; + } + QWidget* createTransparentWidget(QWidget* parent=nullptr) { auto* w = new QWidget(parent); @@ -156,7 +202,12 @@ private: QFrame* createOverlay(QWidget* mainUI) { - m_topLevel.reset(createTransparentWidget(mainUI)); + if (m_topLevel) { + delete m_topLevel.data(); + m_topLevel.clear(); + } + + m_topLevel = createTransparentWidget(mainUI); m_topLevel->setWindowFlags(m_topLevel->windowFlags() & Qt::FramelessWindowHint); m_topLevel->setGeometry(mainUI->rect()); @@ -171,7 +222,12 @@ private: QFrame* createDialog() { - m_topLevel.reset(new QDialog); + if (m_topLevel) { + delete m_topLevel.data(); + m_topLevel.clear(); + } + + m_topLevel = new QDialog; return createFrame(); } @@ -195,7 +251,7 @@ private: ly->setContentsMargins(0, 0, 0, 0); } - auto* grid = new QGridLayout(m_topLevel.get()); + auto* grid = new QGridLayout(m_topLevel.data()); grid->addWidget(createTransparentWidget(), 0, 1); grid->addWidget(createTransparentWidget(), 2, 1); grid->addWidget(createTransparentWidget(), 1, 0); -- cgit v1.3.1 From 05231eab45f86e3d0d342c429e35c8f7c813ea42 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 15 Dec 2019 22:35:02 -0500 Subject: temporary fix to keep MO locked for all processes when closing save main window settings in closeEvent() --- src/main.cpp | 1 - src/mainwindow.cpp | 22 ++++++++++++++++++++++ src/processrunner.cpp | 26 ++++++++++++++++++-------- src/spawn.cpp | 6 ++++-- src/uilocker.cpp | 5 +++++ src/uilocker.h | 1 + 6 files changed, 50 insertions(+), 11 deletions(-) (limited to 'src/uilocker.cpp') diff --git a/src/main.cpp b/src/main.cpp index eeabd497..29d2d02c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -745,7 +745,6 @@ int runApplication(MOApplication &application, SingleInstance &instance, splash.finish(&mainWindow); res = application.exec(); - mainWindow.onBeforeClose(); mainWindow.close(); NexusInterface::instance(&pluginContainer) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d1578d85..284c33e3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1306,6 +1306,21 @@ void MainWindow::onBeforeClose() void MainWindow::closeEvent(QCloseEvent* event) { + if (isVisible()) { + // this is messy + // + // the main problem this is solving is when closing MO, then getting the + // lock overlay because processes are still running, then pressing the X + // again + // + // in this case, closeEvent() is _not_ called for the second event and the + // window is immediately hidden + // + // this always saves the settings here; in the event where a lock overlay + // is then shown, it might save settings multiple times, but it's harmless + onBeforeClose(); + } + // this happens for two reasons: // 1) the user requested to close the window, such as clicking the X // 2) close() is called in runApplication() after application.exec() @@ -1324,6 +1339,13 @@ void MainWindow::closeEvent(QCloseEvent* event) return; } + if (UILocker::instance().locked()) { + // don't bother asking the user to confirm if the ui is already locked + event->ignore(); + ExitModOrganizer(Exit::Force); + return; + } + if (ModOrganizerExiting()) { // ignore repeated attempts event->ignore(); diff --git a/src/processrunner.cpp b/src/processrunner.cpp index aead42d1..945d61c3 100644 --- a/src/processrunner.cpp +++ b/src/processrunner.cpp @@ -344,6 +344,9 @@ ProcessRunner::Results waitForProcessesThreadImpl( // processes wait = std::min(wait * 2, milliseconds(2000)); } + + log::debug("waiting for processes interrupted"); + return ProcessRunner::ForceUnlocked; } void waitForProcessesThread( @@ -374,9 +377,12 @@ ProcessRunner::Results waitForProcesses( if (!::AssignProcessToJobObject(job.get(), h)) { const auto e = GetLastError(); - log::error( - "can't assign process to job to wait for processes, {}", - formatSystemMessage(e)); + // this happens when closing MO while multiple processes are running, + // so the logging is disabled until it gets fixed + + //log::error( + // "can't assign process to job to wait for processes, {}", + // formatSystemMessage(e)); // keep going } @@ -871,11 +877,12 @@ ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock( auto r = Error; - withLock([&](auto& ls) { for (;;) { + withLock([&](auto& ls) { const auto processes = getRunningUSVFSProcesses(); if (processes.empty()) { - break; + r = Completed; + return; } r = waitForProcesses(processes, ls); @@ -886,11 +893,14 @@ ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock( } // this process is completed, check for others - } - - r = Completed; + r = Running; }); + if (r != Running) { + break; + } + } + return r; } diff --git a/src/spawn.cpp b/src/spawn.cpp index f95846c8..33bdbc05 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -498,14 +498,16 @@ DWORD spawn(const SpawnParameters& sp, HANDLE& processHandle) const auto wcommandLine = commandLine.toStdWString(); const auto wcwd = cwd.toStdWString(); + const DWORD flags = CREATE_BREAKAWAY_FROM_JOB; + if (sp.hooked) { success = ::CreateProcessHooked( nullptr, const_cast(wcommandLine.c_str()), nullptr, nullptr, - inheritHandles, 0, nullptr, wcwd.c_str(), &si, &pi); + inheritHandles, flags, nullptr, wcwd.c_str(), &si, &pi); } else { success = ::CreateProcess( nullptr, const_cast(wcommandLine.c_str()), nullptr, nullptr, - inheritHandles, 0, nullptr, wcwd.c_str(), &si, &pi); + inheritHandles, flags, nullptr, wcwd.c_str(), &si, &pi); } const auto e = GetLastError(); diff --git a/src/uilocker.cpp b/src/uilocker.cpp index af9b9b96..07fe7f1b 100644 --- a/src/uilocker.cpp +++ b/src/uilocker.cpp @@ -461,6 +461,11 @@ std::shared_ptr UILocker::lock(Reasons reason) return ls; } +bool UILocker::locked() const +{ + return !m_sessions.empty(); +} + void UILocker::unlock(Session* s) { auto itor = m_sessions.begin(); diff --git a/src/uilocker.h b/src/uilocker.h index d8c22999..cc467184 100644 --- a/src/uilocker.h +++ b/src/uilocker.h @@ -70,6 +70,7 @@ public: void setUserInterface(QWidget* parent); std::shared_ptr lock(Reasons reason); + bool locked() const; Results result() const; -- cgit v1.3.1