Warning, file /plasma/drkonqi/src/statusnotifier_activationclosetimer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2016 Kai Uwe Broulik <kde@privat.broulik.de> 0004 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0005 */ 0006 0007 #include "statusnotifier_activationclosetimer.h" 0008 0009 #include <QDBusConnectionInterface> 0010 0011 #include <KIdleTime> 0012 0013 #include "drkonqi_debug.h" 0014 0015 void ActivationCloseTimer::refresh() 0016 { 0017 qCDebug(DRKONQI_LOG) << m_idle << m_pendingActivations << m_closeTimer.isActive(); 0018 if (m_idle) { 0019 m_closeTimer.stop(); 0020 } else { // not idle 0021 if (m_pendingActivations > 0) { // going for auto activation instead of closing 0022 m_closeTimer.stop(); 0023 } else if (!m_closeTimer.isActive()) { // otherwise we may auto close if not already running 0024 m_closeTimer.start(); 0025 } 0026 } 0027 } 0028 0029 void ActivationCloseTimer::watchIdle(IdleWatcher *idleWatcher) 0030 { 0031 // if nobody bothered to look at the crash after 1 minute, just close 0032 m_closeTimer.setSingleShot(true); 0033 m_closeTimer.setInterval(m_closeTimeout); 0034 connect(&m_closeTimer, &QTimer::timeout, this, &ActivationCloseTimer::autoClose); 0035 m_closeTimer.start(); 0036 0037 // make sure the user doesn't miss the SNI by stopping the auto hide timer when the session becomes idle 0038 connect(idleWatcher, &IdleWatcher::idle, this, [this] { 0039 m_idle = true; 0040 refresh(); 0041 }); 0042 connect(idleWatcher, &IdleWatcher::notIdle, this, [this] { 0043 m_idle = false; 0044 refresh(); 0045 }); 0046 0047 idleWatcher->start(); 0048 } 0049 0050 void ActivationCloseTimer::watchDBus(DBusServiceWatcher *watcher) 0051 { 0052 // Should the SNI host implode and not return within 10s, automatically 0053 // open the dialog. 0054 // We are tracking the related Notifications service here, because actually 0055 // tracking the Host interface is fairly involved with no tangible advantage. 0056 0057 auto activationTimer = new QTimer(this); 0058 activationTimer->setInterval(m_activationTimeout); 0059 connect(activationTimer, &QTimer::timeout, this, &ActivationCloseTimer::autoActivate); 0060 0061 connect(watcher, &DBusServiceWatcher::serviceUnregistered, activationTimer, [this, activationTimer] { 0062 ++m_pendingActivations; 0063 activationTimer->start(); 0064 refresh(); 0065 }); 0066 connect(watcher, &DBusServiceWatcher::serviceRegistered, activationTimer, [this, activationTimer] { 0067 if (m_pendingActivations > 0) { 0068 --m_pendingActivations; 0069 } 0070 activationTimer->stop(); 0071 refresh(); 0072 }); 0073 0074 watcher->start(); 0075 } 0076 0077 void ActivationCloseTimer::start(DBusServiceWatcher *dbusWatcher, IdleWatcher *idleWatcher) 0078 { 0079 connect(this, &ActivationCloseTimer::autoActivate, this, [this] { 0080 m_closeTimer.stop(); // make double sure we don't close once activated! 0081 }); 0082 watchDBus(dbusWatcher); 0083 watchIdle(idleWatcher); 0084 } 0085 0086 void IdleWatcher::start() 0087 { 0088 // make sure the user doesn't miss the SNI by stopping the auto hide timer when the session becomes idle 0089 const auto idleTime = 30s; 0090 const int idleId = KIdleTime::instance()->addIdleTimeout(int(std::chrono::milliseconds(idleTime).count())); 0091 connect(KIdleTime::instance(), static_cast<void (KIdleTime::*)(int, int)>(&KIdleTime::timeoutReached), this, [this, idleId](int id) { 0092 if (idleId == id) { 0093 Q_EMIT idle(); 0094 } 0095 // this is apparently needed or else resumingFromIdle is never called 0096 KIdleTime::instance()->catchNextResumeEvent(); 0097 }); 0098 connect(KIdleTime::instance(), &KIdleTime::resumingFromIdle, this, &IdleWatcher::notIdle); 0099 0100 if (std::chrono::milliseconds(KIdleTime::instance()->idleTime()) >= idleTime) { 0101 Q_EMIT idle(); 0102 } 0103 } 0104 0105 QVector<QString> DBusServiceWatcher::serviceNames() const 0106 { 0107 return m_serviceNames; 0108 } 0109 0110 void DBusServiceWatcher::start() 0111 { 0112 const QDBusConnection sessionBus = QDBusConnection::sessionBus(); 0113 const QDBusConnectionInterface *sessionInterface = sessionBus.interface(); 0114 Q_ASSERT(sessionInterface); 0115 0116 m_watcher = new QDBusServiceWatcher(this); 0117 m_watcher->setConnection(sessionBus); 0118 m_watcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange); 0119 for (const auto &serviceName : m_serviceNames) { 0120 m_watcher->addWatchedService(serviceName); 0121 0122 // if not currently available queue the activation - this is in case the service isn't available *right now* 0123 // in which case we'll not get any registration events 0124 if (!sessionInterface->isServiceRegistered(serviceName)) { 0125 Q_EMIT serviceUnregistered(); 0126 } 0127 } 0128 0129 connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &DBusServiceWatcher::serviceUnregistered); 0130 connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &DBusServiceWatcher::serviceRegistered); 0131 } 0132 0133 void ActivationCloseTimer::setActivationTimeout(std::chrono::milliseconds timeout) 0134 { 0135 m_activationTimeout = timeout; 0136 } 0137 0138 void ActivationCloseTimer::setCloseTimeout(std::chrono::milliseconds timeout) 0139 { 0140 m_closeTimeout = timeout; 0141 }