Skip to content

Commit 317fd61

Browse files
committed
fix: keep updater dialogs in foreground
1 parent 02a29e7 commit 317fd61

2 files changed

Lines changed: 212 additions & 7 deletions

File tree

src/gui/updater/appimageupdater.cpp

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,113 @@
2323
#include <QDialogButtonBox>
2424
#include <QPushButton>
2525
#include <QStyle>
26+
#include <QApplication>
27+
#include <QTimer>
2628

2729
namespace OCC {
30+
namespace {
31+
void raiseAppImageDialog(QWidget *widget);
32+
33+
QWidget *appImageDialogParent()
34+
{
35+
if (auto *active = QApplication::activeWindow()) {
36+
return active;
37+
}
38+
39+
if (auto *focus = QApplication::focusWidget()) {
40+
return focus->window();
41+
}
42+
43+
return nullptr;
44+
}
45+
46+
bool attachAndOpenAppImageDialog(QDialog *dialog, const bool removeContextHelpButton, const bool requireParent)
47+
{
48+
if (!dialog || dialog->isVisible()) {
49+
return dialog != nullptr;
50+
}
51+
52+
auto *parent = appImageDialogParent();
53+
if (requireParent && !parent) {
54+
return false;
55+
}
56+
57+
if (parent) {
58+
dialog->setParent(parent, dialog->windowFlags());
59+
dialog->setWindowModality(Qt::WindowModal);
60+
} else {
61+
dialog->setWindowModality(Qt::ApplicationModal);
62+
}
63+
64+
auto flags = dialog->windowFlags() | Qt::WindowStaysOnTopHint;
65+
if (removeContextHelpButton) {
66+
flags &= ~Qt::WindowContextHelpButtonHint;
67+
}
68+
dialog->setWindowFlags(flags);
69+
dialog->open();
70+
raiseAppImageDialog(dialog);
71+
return true;
72+
}
73+
74+
void presentAppImageDialog(QDialog *dialog, const bool removeContextHelpButton)
75+
{
76+
if (!dialog) {
77+
return;
78+
}
79+
80+
if (attachAndOpenAppImageDialog(dialog, removeContextHelpButton, true)) {
81+
return;
82+
}
83+
84+
auto *timer = new QTimer(dialog);
85+
timer->setInterval(150);
86+
timer->setSingleShot(false);
87+
QObject::connect(timer, &QTimer::timeout, dialog, [dialog, removeContextHelpButton, timer]() {
88+
if (!dialog) {
89+
timer->stop();
90+
timer->deleteLater();
91+
return;
92+
}
93+
94+
if (attachAndOpenAppImageDialog(dialog, removeContextHelpButton, true)) {
95+
timer->stop();
96+
timer->deleteLater();
97+
}
98+
});
99+
timer->start();
100+
101+
QTimer::singleShot(2000, dialog, [dialog, removeContextHelpButton, timer]() {
102+
if (!dialog || dialog->isVisible()) {
103+
return;
104+
}
105+
106+
attachAndOpenAppImageDialog(dialog, removeContextHelpButton, false);
107+
if (timer) {
108+
timer->stop();
109+
timer->deleteLater();
110+
}
111+
});
112+
113+
QObject::connect(qApp, &QApplication::focusChanged, dialog, [dialog]() {
114+
if (!dialog || !dialog->isVisible()) {
115+
return;
116+
}
117+
118+
raiseAppImageDialog(dialog);
119+
});
120+
}
121+
122+
void raiseAppImageDialog(QWidget *widget)
123+
{
124+
if (!widget) {
125+
return;
126+
}
127+
128+
widget->showNormal();
129+
widget->raise();
130+
widget->activateWindow();
131+
}
132+
} // namespace
28133

29134
using namespace Qt::StringLiterals;
30135

@@ -204,7 +309,6 @@ void AppImageUpdater::showUpdateErrorDialog(const QString &targetVersion)
204309
{
205310
auto *msgBox = new QDialog;
206311
msgBox->setAttribute(Qt::WA_DeleteOnClose);
207-
msgBox->setWindowFlags(msgBox->windowFlags() & ~Qt::WindowContextHelpButtonHint);
208312

209313
const auto infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation);
210314
const auto iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
@@ -249,7 +353,7 @@ void AppImageUpdater::showUpdateErrorDialog(const QString &targetVersion)
249353

250354
layout->addWidget(bb);
251355

252-
msgBox->open();
356+
presentAppImageDialog(msgBox, true);
253357
}
254358

255359
bool AppImageUpdater::handleStartup()

src/gui/updater/ocupdater.cpp

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,109 @@
2020
#include <cstdio>
2121

2222
namespace OCC {
23+
namespace {
24+
void raiseUpdaterDialog(QWidget *widget);
25+
26+
QWidget *updaterDialogParent()
27+
{
28+
if (auto *active = QApplication::activeWindow()) {
29+
return active;
30+
}
31+
32+
if (auto *focus = QApplication::focusWidget()) {
33+
return focus->window();
34+
}
35+
36+
return nullptr;
37+
}
38+
39+
bool attachAndOpenUpdaterDialog(QDialog *dialog, const bool removeContextHelpButton, const bool requireParent)
40+
{
41+
if (!dialog || dialog->isVisible()) {
42+
return dialog != nullptr;
43+
}
44+
45+
auto *parent = updaterDialogParent();
46+
if (requireParent && !parent) {
47+
return false;
48+
}
49+
50+
if (parent) {
51+
dialog->setParent(parent, dialog->windowFlags());
52+
dialog->setWindowModality(Qt::WindowModal);
53+
} else {
54+
dialog->setWindowModality(Qt::ApplicationModal);
55+
}
56+
57+
auto flags = dialog->windowFlags() | Qt::WindowStaysOnTopHint;
58+
if (removeContextHelpButton) {
59+
flags &= ~Qt::WindowContextHelpButtonHint;
60+
}
61+
dialog->setWindowFlags(flags);
62+
dialog->open();
63+
raiseUpdaterDialog(dialog);
64+
return true;
65+
}
66+
67+
void presentUpdaterDialog(QDialog *dialog, const bool removeContextHelpButton)
68+
{
69+
if (!dialog) {
70+
return;
71+
}
72+
73+
if (attachAndOpenUpdaterDialog(dialog, removeContextHelpButton, true)) {
74+
return;
75+
}
76+
77+
auto *timer = new QTimer(dialog);
78+
timer->setInterval(150);
79+
timer->setSingleShot(false);
80+
QObject::connect(timer, &QTimer::timeout, dialog, [dialog, removeContextHelpButton, timer]() {
81+
if (!dialog) {
82+
timer->stop();
83+
timer->deleteLater();
84+
return;
85+
}
86+
87+
if (attachAndOpenUpdaterDialog(dialog, removeContextHelpButton, true)) {
88+
timer->stop();
89+
timer->deleteLater();
90+
}
91+
});
92+
timer->start();
93+
94+
QTimer::singleShot(2000, dialog, [dialog, removeContextHelpButton, timer]() {
95+
if (!dialog || dialog->isVisible()) {
96+
return;
97+
}
98+
99+
attachAndOpenUpdaterDialog(dialog, removeContextHelpButton, false);
100+
if (timer) {
101+
timer->stop();
102+
timer->deleteLater();
103+
}
104+
});
105+
106+
QObject::connect(qApp, &QApplication::focusChanged, dialog, [dialog]() {
107+
if (!dialog || !dialog->isVisible()) {
108+
return;
109+
}
110+
111+
raiseUpdaterDialog(dialog);
112+
});
113+
}
114+
115+
void raiseUpdaterDialog(QWidget *widget)
116+
{
117+
if (!widget) {
118+
return;
119+
}
120+
121+
widget->showNormal();
122+
widget->raise();
123+
widget->activateWindow();
124+
}
125+
} // namespace
23126

24127
UpdaterScheduler::UpdaterScheduler(QObject *parent)
25128
: QObject(parent)
@@ -104,7 +207,7 @@ bool OCUpdater::performUpdate()
104207
slotStartInstaller();
105208
}
106209
});
107-
messageBoxStartInstaller->open();
210+
presentUpdaterDialog(messageBoxStartInstaller, false);
108211
}
109212
return false;
110213
}
@@ -359,7 +462,6 @@ void NSISUpdater::showNoUrlDialog(const UpdateInfo &info)
359462
// if the version tag is set, there is a newer version.
360463
auto *msgBox = new QDialog;
361464
msgBox->setAttribute(Qt::WA_DeleteOnClose);
362-
msgBox->setWindowFlags(msgBox->windowFlags() & ~Qt::WindowContextHelpButtonHint);
363465

364466
QIcon infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation);
365467
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
@@ -399,14 +501,13 @@ void NSISUpdater::showNoUrlDialog(const UpdateInfo &info)
399501

400502
layout->addWidget(bb);
401503

402-
msgBox->open();
504+
presentUpdaterDialog(msgBox, true);
403505
}
404506

405507
void NSISUpdater::showUpdateErrorDialog(const QString &targetVersion)
406508
{
407509
auto msgBox = new QDialog;
408510
msgBox->setAttribute(Qt::WA_DeleteOnClose);
409-
msgBox->setWindowFlags(msgBox->windowFlags() & ~Qt::WindowContextHelpButtonHint);
410511

411512
QIcon infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation);
412513
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
@@ -454,7 +555,7 @@ void NSISUpdater::showUpdateErrorDialog(const QString &targetVersion)
454555

455556
layout->addWidget(bb);
456557

457-
msgBox->open();
558+
presentUpdaterDialog(msgBox, true);
458559
}
459560

460561
bool NSISUpdater::handleStartup()

0 commit comments

Comments
 (0)