File indexing completed on 2024-12-01 09:52:19

0001 /* This file is part of the KDE libraries
0002  * SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include "widgetbasedpoller.h"
0008 
0009 #include <QEvent>
0010 #include <QTimer>
0011 #include <QWindow>
0012 
0013 WidgetBasedPoller::WidgetBasedPoller(QObject *parent)
0014     : AbstractSystemPoller(parent)
0015 {
0016 }
0017 
0018 WidgetBasedPoller::~WidgetBasedPoller()
0019 {
0020 }
0021 
0022 bool WidgetBasedPoller::isAvailable()
0023 {
0024     return true;
0025 }
0026 
0027 bool WidgetBasedPoller::setUpPoller()
0028 {
0029     m_pollTimer = new QTimer(this);
0030 
0031     // setup idle timer, with some smart polling
0032     connect(m_pollTimer, &QTimer::timeout, this, &WidgetBasedPoller::poll);
0033 
0034     m_grabber = new QWindow();
0035     m_grabber->setFlag(Qt::X11BypassWindowManagerHint);
0036     m_grabber->setPosition(-1000, -1000);
0037     m_grabber->installEventFilter(this);
0038     m_grabber->setObjectName(QStringLiteral("KIdleGrabberWidget"));
0039 
0040     return additionalSetUp();
0041 }
0042 
0043 void WidgetBasedPoller::unloadPoller()
0044 {
0045     m_pollTimer->deleteLater();
0046     m_grabber->deleteLater();
0047 }
0048 
0049 QList<int> WidgetBasedPoller::timeouts() const
0050 {
0051     return m_timeouts;
0052 }
0053 
0054 void WidgetBasedPoller::addTimeout(int nextTimeout)
0055 {
0056     m_timeouts.append(nextTimeout);
0057     poll();
0058 }
0059 
0060 bool WidgetBasedPoller::eventFilter(QObject *object, QEvent *event)
0061 {
0062     if (object == m_grabber && (event->type() == QEvent::MouseMove || event->type() == QEvent::KeyPress)) {
0063         detectedActivity();
0064         return true;
0065     } else if (object != m_grabber) {
0066         // If it's not the grabber, fallback to default event filter
0067         return false;
0068     }
0069 
0070     // Otherwise, simply ignore it
0071     return false;
0072 }
0073 
0074 void WidgetBasedPoller::waitForActivity()
0075 {
0076     m_grabber->show();
0077     m_grabber->setMouseGrabEnabled(true);
0078     m_grabber->setKeyboardGrabEnabled(true);
0079 }
0080 
0081 void WidgetBasedPoller::detectedActivity()
0082 {
0083     stopCatchingIdleEvents();
0084     Q_EMIT resumingFromIdle();
0085 }
0086 
0087 void WidgetBasedPoller::releaseInputLock()
0088 {
0089     m_grabber->setMouseGrabEnabled(false);
0090     m_grabber->setKeyboardGrabEnabled(false);
0091     m_grabber->hide();
0092 }
0093 
0094 int WidgetBasedPoller::poll()
0095 {
0096     int idle = getIdleTime();
0097 
0098     // Check if we reached a timeout..
0099     for (int timeOut : std::as_const(m_timeouts)) {
0100         if ((timeOut - idle < 300 && timeOut >= idle) || (idle - timeOut < 300 && idle > timeOut)) {
0101             // Bingo!
0102             Q_EMIT timeoutReached(timeOut);
0103         }
0104     }
0105 
0106     // Let's check the timer now!
0107     int mintime = 0;
0108 
0109     for (int i : std::as_const(m_timeouts)) {
0110         if (i > idle && (i < mintime || mintime == 0)) {
0111             mintime = i;
0112         }
0113     }
0114 
0115     // qDebug() << "mintime " << mintime << "idle " << idle;
0116 
0117     if (mintime != 0) {
0118         m_pollTimer->start(mintime - idle);
0119     } else {
0120         m_pollTimer->stop();
0121     }
0122 
0123     return idle;
0124 }
0125 
0126 int WidgetBasedPoller::forcePollRequest()
0127 {
0128     return poll();
0129 }
0130 
0131 void WidgetBasedPoller::removeTimeout(int timeout)
0132 {
0133     m_timeouts.removeOne(timeout);
0134     poll();
0135 }
0136 
0137 void WidgetBasedPoller::catchIdleEvent()
0138 {
0139     waitForActivity();
0140 }
0141 
0142 void WidgetBasedPoller::stopCatchingIdleEvents()
0143 {
0144     releaseInputLock();
0145 }
0146 
0147 #include "moc_widgetbasedpoller.cpp"