diff --git a/tools/chatgui/src/message_notification.cpp b/tools/chatgui/src/message_notification.cpp index 47cb912f..fb198b00 100644 --- a/tools/chatgui/src/message_notification.cpp +++ b/tools/chatgui/src/message_notification.cpp @@ -13,8 +13,8 @@ #include #include -MessageNotification::MessageNotification(QWidget* parent) - : QWidget(parent, Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus) +MessageNotification::MessageNotification() + : QWidget(nullptr, Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus) , m_activity(new UserActivityMonitor(this)) { setObjectName("messageNotification"); @@ -67,9 +67,10 @@ MessageNotification::~MessageNotification() { qPrintable(m_target), int(isVisible()), int(m_hideTimer.isActive())); } -void MessageNotification::showMessage(const QString& target, const QString& sender, const QString& channel, const QRect& trayGeometry) { +void MessageNotification::showMessage(const QString& target, const QString& sender, const QString& channel, + const QRect& trayGeometry, QScreen* preferredScreen) { QScreen* screen = trayGeometry.isEmpty() ? nullptr : QGuiApplication::screenAt(trayGeometry.center()); - if (!screen && parentWidget()) screen = parentWidget()->screen(); + if (!screen) screen = preferredScreen; if (!screen) screen = QGuiApplication::primaryScreen(); if (!screen || screen->availableGeometry().isEmpty()) { GUI_ERROR("notification: no available screen target=%s", qPrintable(target)); diff --git a/tools/chatgui/src/message_notification.h b/tools/chatgui/src/message_notification.h index ed0a8677..4ad98154 100644 --- a/tools/chatgui/src/message_notification.h +++ b/tools/chatgui/src/message_notification.h @@ -6,14 +6,16 @@ #include class QLabel; +class QScreen; class UserActivityMonitor; class MessageNotification : public QWidget { Q_OBJECT public: - explicit MessageNotification(QWidget* parent = nullptr); + MessageNotification(); ~MessageNotification() override; - void showMessage(const QString& target, const QString& sender, const QString& channel, const QRect& trayGeometry); + void showMessage(const QString& target, const QString& sender, const QString& channel, + const QRect& trayGeometry, QScreen* preferredScreen = nullptr); void dismiss(const char* reason); signals: diff --git a/tools/chatgui/tests/test_message_notification.cpp b/tools/chatgui/tests/test_message_notification.cpp index 62ced741..279aee88 100644 --- a/tools/chatgui/tests/test_message_notification.cpp +++ b/tools/chatgui/tests/test_message_notification.cpp @@ -43,8 +43,9 @@ public slots: requests, (unsigned long long)idle, delayMs, int(calledFromDBus())); if (delayMs) { const QDBusMessage reply = message().createReply(QVariant::fromValue(idle)); + const QDBusConnection bus = connection(); setDelayedReply(true); - QTimer::singleShot(delayMs, this, [reply] { QDBusConnection::sessionBus().send(reply); }); + QTimer::singleShot(delayMs, this, [reply, bus] { bus.send(reply); }); } return idle; } @@ -60,6 +61,13 @@ private slots: qunsetenv("XDG_SESSION_TYPE"); } + void cleanup() { + qunsetenv("XDG_SESSION_TYPE"); +#ifdef UTUN_TEST_ACTIVITY_DBUS + QDBusConnection::disconnectFromBus("notification-test-service"); +#endif + } + void firstSystemActivityAndCancellation() { FakeSystemActivity activity; QSignalSpy spy(&activity, &UserActivityMonitor::activity); @@ -98,11 +106,15 @@ private slots: QWidget hiddenParent; QLineEdit otherWindow; otherWindow.show(); - QApplication::setActiveWindow(&otherWindow); - MessageNotification notification(&hiddenParent); + otherWindow.activateWindow(); + QTRY_COMPARE(QApplication::activeWindow(), &otherWindow); + MessageNotification notification; notification.showMessage("42", "Alice", "Test channel", {}); QVERIFY(notification.isVisible()); + QVERIFY(!notification.parentWidget()); // ОС не должна скрывать уведомление вместе с главным окном. QCOMPARE(QApplication::activeWindow(), &otherWindow); + hiddenParent.showMinimized(); + QVERIFY(notification.isVisible()); QTest::qWait(10200); QVERIFY(notification.isVisible()); // Без активности автоматического таймера нет. QElapsedTimer elapsed; @@ -144,7 +156,8 @@ private slots: #ifdef UTUN_TEST_ACTIVITY_DBUS void gnomeIdleAndStaleReplies() { - auto bus = QDBusConnection::sessionBus(); + // Разные соединения исключают прямой вызов внутри Qt, чтобы задержка действительно прошла через D-Bus. + auto bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "notification-test-service"); QVERIFY(bus.registerService("org.gnome.Mutter.IdleMonitor")); FakeGnomeIdle idle; QVERIFY(bus.registerObject("/org/gnome/Mutter/IdleMonitor/Core", &idle, QDBusConnection::ExportAllSlots));