Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
configure_file(config-kidletime.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kidletime.h )
|
||||
|
||||
add_library(KF6IdleTime)
|
||||
add_library(KF6::IdleTime ALIAS KF6IdleTime)
|
||||
|
||||
set_target_properties(KF6IdleTime PROPERTIES
|
||||
VERSION ${KIDLETIME_VERSION}
|
||||
SOVERSION ${KIDLETIME_SOVERSION}
|
||||
EXPORT_NAME IdleTime
|
||||
)
|
||||
|
||||
target_sources(KF6IdleTime PRIVATE
|
||||
kidletime.cpp
|
||||
kabstractidletimepoller.cpp
|
||||
kwindowbasedidletimepoller.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(KF6IdleTime
|
||||
HEADER logging.h
|
||||
IDENTIFIER KIDLETIME
|
||||
CATEGORY_NAME kf.idletime
|
||||
OLD_CATEGORY_NAMES org.kde.kf5.idletime
|
||||
DESCRIPTION "kidletime (lib)"
|
||||
EXPORT KIDLETIME
|
||||
)
|
||||
|
||||
ecm_generate_export_header(KF6IdleTime
|
||||
BASE_NAME KIdleTime
|
||||
GROUP_BASE_NAME KF
|
||||
VERSION ${KF_VERSION}
|
||||
USE_VERSION_HEADER
|
||||
DEPRECATED_BASE_VERSION 0
|
||||
DEPRECATION_VERSIONS
|
||||
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
|
||||
)
|
||||
|
||||
target_include_directories(KF6IdleTime INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KIdleTime>")
|
||||
|
||||
target_link_libraries(KF6IdleTime PUBLIC Qt6::Core)
|
||||
target_link_libraries(KF6IdleTime PRIVATE Qt6::Gui)
|
||||
|
||||
add_subdirectory(plugins)
|
||||
|
||||
ecm_generate_headers(KIdleTime_HEADERS
|
||||
HEADER_NAMES
|
||||
KIdleTime
|
||||
|
||||
REQUIRED_HEADERS KIdleTime_HEADERS
|
||||
)
|
||||
|
||||
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kidletime_export.h
|
||||
${KIdleTime_HEADERS}
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KIdleTime COMPONENT Devel
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
kabstractidletimepoller_p.h
|
||||
DESTINATION
|
||||
${KDE_INSTALL_INCLUDEDIR_KF}/KIdleTime/private
|
||||
COMPONENT
|
||||
Devel
|
||||
)
|
||||
|
||||
install(TARGETS KF6IdleTime EXPORT KF6IdleTimeTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
|
||||
ecm_qt_install_logging_categories(
|
||||
EXPORT KIDLETIME
|
||||
FILE kidletime.categories
|
||||
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
||||
)
|
||||
|
||||
if(BUILD_QCH)
|
||||
ecm_add_qch(
|
||||
KF6IdleTime_QCH
|
||||
NAME KIdleTime
|
||||
BASE_NAME KF6IdleTime
|
||||
VERSION ${KF_VERSION}
|
||||
ORG_DOMAIN org.kde
|
||||
SOURCES # using only public headers, to cover only public API
|
||||
${KIdleTime_HEADERS}
|
||||
MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
|
||||
LINK_QCHS
|
||||
Qt6Core_QCH
|
||||
INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
BLANK_MACROS
|
||||
KIDLETIME_EXPORT
|
||||
"KIDLETIME_DEPRECATED_VERSION(x, y, t)"
|
||||
TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
|
||||
QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
|
||||
COMPONENT Devel
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/* config-kidletime.h. Generated by cmake from config-kidletime.h.cmake */
|
||||
|
||||
/* Define if you have the XScreensaver extension */
|
||||
#cmakedefine01 HAVE_XSCREENSAVER
|
||||
|
||||
/* Define if you have the XSync extension */
|
||||
#cmakedefine01 HAVE_XSYNC
|
||||
|
||||
/* Define if you have X11 */
|
||||
#cmakedefine01 HAVE_X11
|
||||
@@ -0,0 +1,18 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
|
||||
KAbstractIdleTimePoller::KAbstractIdleTimePoller(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
KAbstractIdleTimePoller::~KAbstractIdleTimePoller()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_kabstractidletimepoller_p.cpp"
|
||||
@@ -0,0 +1,47 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef KABSTRACTIDLETIMEPOLLER_P_H
|
||||
#define KABSTRACTIDLETIMEPOLLER_P_H
|
||||
|
||||
#include <kidletime_export.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#define KAbstractIdleTimePoller_iid "org.kde.kidletime.KAbstractIdleTimePoller"
|
||||
|
||||
class KIDLETIME_EXPORT KAbstractIdleTimePoller : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KAbstractIdleTimePoller(QObject *parent = nullptr);
|
||||
~KAbstractIdleTimePoller() override;
|
||||
|
||||
virtual bool isAvailable() = 0;
|
||||
virtual bool setUpPoller() = 0;
|
||||
virtual void unloadPoller() = 0;
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void addTimeout(int nextTimeout) = 0;
|
||||
virtual void removeTimeout(int nextTimeout) = 0;
|
||||
|
||||
// TODO KF6: Make it a public method
|
||||
virtual QList<int> timeouts() const = 0; // clazy:exclude=const-signal-or-slot
|
||||
|
||||
virtual int forcePollRequest() = 0;
|
||||
virtual void catchIdleEvent() = 0;
|
||||
virtual void stopCatchingIdleEvents() = 0;
|
||||
virtual void simulateUserActivity() = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
void resumingFromIdle();
|
||||
void timeoutReached(int msec);
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(KAbstractIdleTimePoller, KAbstractIdleTimePoller_iid)
|
||||
|
||||
#endif /* KABSTRACTIDLETIMEPOLLER_P_H */
|
||||
@@ -0,0 +1,327 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "kidletime.h"
|
||||
|
||||
#include <config-kidletime.h>
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonArray>
|
||||
#include <QPluginLoader>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
|
||||
class KIdleTimeHelper
|
||||
{
|
||||
public:
|
||||
KIdleTimeHelper()
|
||||
: q(nullptr)
|
||||
{
|
||||
}
|
||||
~KIdleTimeHelper()
|
||||
{
|
||||
delete q;
|
||||
}
|
||||
KIdleTimeHelper(const KIdleTimeHelper &) = delete;
|
||||
KIdleTimeHelper &operator=(const KIdleTimeHelper &) = delete;
|
||||
KIdleTime *q;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(KIdleTimeHelper, s_globalKIdleTime)
|
||||
|
||||
KIdleTime *KIdleTime::instance()
|
||||
{
|
||||
if (!s_globalKIdleTime()->q) {
|
||||
new KIdleTime;
|
||||
}
|
||||
|
||||
return s_globalKIdleTime()->q;
|
||||
}
|
||||
|
||||
class KIdleTimePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(KIdleTime)
|
||||
KIdleTime *q_ptr;
|
||||
|
||||
public:
|
||||
KIdleTimePrivate()
|
||||
: catchResume(false)
|
||||
, currentId(0)
|
||||
{
|
||||
}
|
||||
|
||||
void loadSystem();
|
||||
void unloadCurrentSystem();
|
||||
void resumingFromIdle();
|
||||
void timeoutReached(int msec);
|
||||
|
||||
QPointer<KAbstractIdleTimePoller> poller;
|
||||
bool catchResume;
|
||||
|
||||
int currentId;
|
||||
QHash<int, int> associations;
|
||||
};
|
||||
|
||||
KIdleTime::KIdleTime()
|
||||
: QObject(nullptr)
|
||||
, d_ptr(new KIdleTimePrivate())
|
||||
{
|
||||
Q_ASSERT(!s_globalKIdleTime()->q);
|
||||
s_globalKIdleTime()->q = this;
|
||||
|
||||
d_ptr->q_ptr = this;
|
||||
|
||||
Q_D(KIdleTime);
|
||||
d->loadSystem();
|
||||
|
||||
connect(d->poller.data(), &KAbstractIdleTimePoller::resumingFromIdle, this, [d]() {
|
||||
d->resumingFromIdle();
|
||||
});
|
||||
connect(d->poller.data(), &KAbstractIdleTimePoller::timeoutReached, this, [d](int msec) {
|
||||
d->timeoutReached(msec);
|
||||
});
|
||||
}
|
||||
|
||||
KIdleTime::~KIdleTime()
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
d->unloadCurrentSystem();
|
||||
}
|
||||
|
||||
void KIdleTime::catchNextResumeEvent()
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
|
||||
if (!d->catchResume && d->poller) {
|
||||
d->catchResume = true;
|
||||
d->poller.data()->catchIdleEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTime::stopCatchingResumeEvent()
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
|
||||
if (d->catchResume && d->poller) {
|
||||
d->catchResume = false;
|
||||
d->poller.data()->stopCatchingIdleEvents();
|
||||
}
|
||||
}
|
||||
|
||||
int KIdleTime::addIdleTimeout(int msec)
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
if (Q_UNLIKELY(msec < 0)) {
|
||||
qCWarning(KIDLETIME, "KIdleTime::addIdleTimeout: invalid timeout: %d", msec);
|
||||
return 0;
|
||||
}
|
||||
if (Q_UNLIKELY(!d->poller)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->poller.data()->addTimeout(msec);
|
||||
|
||||
++d->currentId;
|
||||
d->associations[d->currentId] = msec;
|
||||
|
||||
return d->currentId;
|
||||
}
|
||||
|
||||
void KIdleTime::removeIdleTimeout(int identifier)
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
|
||||
const auto it = d->associations.constFind(identifier);
|
||||
if (it == d->associations.cend() || !d->poller) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int msec = it.value();
|
||||
|
||||
d->associations.erase(it);
|
||||
|
||||
const bool isFound = std::any_of(d->associations.cbegin(), d->associations.cend(), [msec](int i) {
|
||||
return i == msec;
|
||||
});
|
||||
|
||||
if (!isFound) {
|
||||
d->poller.data()->removeTimeout(msec);
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTime::removeAllIdleTimeouts()
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
|
||||
std::vector<int> removed;
|
||||
|
||||
for (auto it = d->associations.cbegin(); it != d->associations.cend(); ++it) {
|
||||
const int msec = it.value();
|
||||
const bool alreadyIns = std::find(removed.cbegin(), removed.cend(), msec) != removed.cend();
|
||||
if (!alreadyIns && d->poller) {
|
||||
removed.push_back(msec);
|
||||
d->poller.data()->removeTimeout(msec);
|
||||
}
|
||||
}
|
||||
|
||||
d->associations.clear();
|
||||
}
|
||||
|
||||
static QStringList pluginCandidates()
|
||||
{
|
||||
QStringList ret;
|
||||
|
||||
const QStringList libPath = QCoreApplication::libraryPaths();
|
||||
for (const QString &path : libPath) {
|
||||
#ifdef Q_OS_MACOS
|
||||
const QDir pluginDir(path + QStringLiteral("/kf6/kidletime"));
|
||||
#else
|
||||
const QDir pluginDir(path + QStringLiteral("/kf6/org.kde.kidletime.platforms"));
|
||||
#endif
|
||||
if (!pluginDir.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto entries = pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
ret.reserve(ret.size() + entries.size());
|
||||
for (const QString &entry : entries) {
|
||||
ret << pluginDir.absoluteFilePath(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool checkPlatform(const QJsonObject &metadata, const QString &platformName)
|
||||
{
|
||||
const QJsonArray platforms = metadata.value(QStringLiteral("MetaData")).toObject().value(QStringLiteral("platforms")).toArray();
|
||||
return std::any_of(platforms.begin(), platforms.end(), [&platformName](const QJsonValue &value) {
|
||||
return QString::compare(platformName, value.toString(), Qt::CaseInsensitive) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
static KAbstractIdleTimePoller *loadPoller()
|
||||
{
|
||||
const QString platformName = QGuiApplication::platformName();
|
||||
|
||||
const QList<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
|
||||
for (const QStaticPlugin &staticPlugin : staticPlugins) {
|
||||
const QJsonObject metadata = staticPlugin.metaData();
|
||||
if (metadata.value(QLatin1String("IID")) != QLatin1String(KAbstractIdleTimePoller_iid)) {
|
||||
continue;
|
||||
}
|
||||
if (checkPlatform(metadata, platformName)) {
|
||||
auto *poller = qobject_cast<KAbstractIdleTimePoller *>(staticPlugin.instance());
|
||||
if (poller) {
|
||||
if (poller->isAvailable()) {
|
||||
qCDebug(KIDLETIME) << "Loaded system poller from a static plugin";
|
||||
return poller;
|
||||
}
|
||||
delete poller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QStringList lstPlugins = pluginCandidates();
|
||||
for (const QString &candidate : lstPlugins) {
|
||||
if (!QLibrary::isLibrary(candidate)) {
|
||||
continue;
|
||||
}
|
||||
QPluginLoader loader(candidate);
|
||||
if (checkPlatform(loader.metaData(), platformName)) {
|
||||
auto *poller = qobject_cast<KAbstractIdleTimePoller *>(loader.instance());
|
||||
if (poller) {
|
||||
qCDebug(KIDLETIME) << "Trying plugin" << candidate;
|
||||
if (poller->isAvailable()) {
|
||||
qCDebug(KIDLETIME) << "Using" << candidate << "for platform" << platformName;
|
||||
return poller;
|
||||
}
|
||||
delete poller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCWarning(KIDLETIME) << "Could not find any system poller plugin";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void KIdleTimePrivate::loadSystem()
|
||||
{
|
||||
if (!poller.isNull()) {
|
||||
unloadCurrentSystem();
|
||||
}
|
||||
|
||||
// load plugin
|
||||
poller = loadPoller();
|
||||
|
||||
if (poller && !poller->isAvailable()) {
|
||||
poller = nullptr;
|
||||
}
|
||||
if (!poller.isNull()) {
|
||||
poller.data()->setUpPoller();
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTimePrivate::unloadCurrentSystem()
|
||||
{
|
||||
if (!poller.isNull()) {
|
||||
poller.data()->unloadPoller();
|
||||
poller.data()->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTimePrivate::resumingFromIdle()
|
||||
{
|
||||
Q_Q(KIdleTime);
|
||||
|
||||
if (catchResume) {
|
||||
Q_EMIT q->resumingFromIdle();
|
||||
q->stopCatchingResumeEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTimePrivate::timeoutReached(int msec)
|
||||
{
|
||||
Q_Q(KIdleTime);
|
||||
|
||||
const auto listKeys = associations.keys(msec);
|
||||
|
||||
for (const auto key : listKeys) {
|
||||
Q_EMIT q->timeoutReached(key, msec);
|
||||
}
|
||||
}
|
||||
|
||||
void KIdleTime::simulateUserActivity()
|
||||
{
|
||||
Q_D(KIdleTime);
|
||||
|
||||
if (Q_LIKELY(d->poller)) {
|
||||
d->poller.data()->simulateUserActivity();
|
||||
}
|
||||
}
|
||||
|
||||
int KIdleTime::idleTime() const
|
||||
{
|
||||
Q_D(const KIdleTime);
|
||||
if (Q_LIKELY(d->poller)) {
|
||||
return d->poller.data()->forcePollRequest();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QHash<int, int> KIdleTime::idleTimeouts() const
|
||||
{
|
||||
Q_D(const KIdleTime);
|
||||
|
||||
return d->associations;
|
||||
}
|
||||
|
||||
#include "moc_kidletime.cpp"
|
||||
@@ -0,0 +1,189 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef KIDLETIME_H
|
||||
#define KIDLETIME_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <kidletime_export.h>
|
||||
#include <memory>
|
||||
|
||||
#if __has_include(<chrono>)
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
class KIdleTimePrivate;
|
||||
|
||||
/**
|
||||
* @class KIdleTime kidletime.h KIdleTime
|
||||
*
|
||||
* KIdleTime is a singleton reporting information on idle time. It is useful not
|
||||
* only for finding out about the current idle time of the PC, but also for getting
|
||||
* notified upon idle time events, such as custom timeouts, or user activity.
|
||||
*
|
||||
* @note All the intervals and times in this library are in milliseconds, unless
|
||||
* specified otherwise
|
||||
*
|
||||
* @author Dario Freddi
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
class KIDLETIME_EXPORT KIdleTime : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(KIdleTime)
|
||||
Q_DISABLE_COPY(KIdleTime)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the singleton instance. Use this method to access KIdleTime
|
||||
*
|
||||
* @returns the instance of KIdleTime
|
||||
*/
|
||||
static KIdleTime *instance();
|
||||
|
||||
/**
|
||||
* The destructor
|
||||
*/
|
||||
~KIdleTime() override;
|
||||
|
||||
/**
|
||||
* Retrieves the idle time of the system, in milliseconds
|
||||
*
|
||||
* @returns the idle time of the system
|
||||
*/
|
||||
int idleTime() const;
|
||||
|
||||
/**
|
||||
* Returns the list of timeout identifiers associated with their duration, in milliseconds,
|
||||
* the library is currently listening to.
|
||||
*
|
||||
* @see addIdleTimeout
|
||||
* @see removeIdleTimeout
|
||||
* @see timeoutReached
|
||||
*/
|
||||
QHash<int, int> idleTimeouts() const;
|
||||
|
||||
/**
|
||||
* Attempts to simulate user activity. This implies that after calling this
|
||||
* method, the idle time of the system will become 0 and eventually \link resumingFromIdle \endlink
|
||||
* will be triggered
|
||||
*
|
||||
* @see resumingFromIdle
|
||||
*/
|
||||
void simulateUserActivity();
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Adds a new timeout to catch. When calling this method, after the system will be idle for
|
||||
* \c msec milliseconds, the signal \c timeoutReached will be triggered. Please note that until you will
|
||||
* call \c removeIdleTimeout or \c removeAllIdleTimeouts, the signal will be triggered every
|
||||
* time the system will be idle for \c msec milliseconds. This function also returns an unique
|
||||
* token for the timeout just added to allow easier identification.
|
||||
*
|
||||
* @param msec the time, in milliseconds, after which the signal will be triggered
|
||||
*
|
||||
* @returns an unique identifier for the timeout being added, that will be streamed by timeoutReached
|
||||
*
|
||||
* @see removeIdleTimeout
|
||||
* @see removeAllIdleTimeouts
|
||||
* @see timeoutReached
|
||||
*
|
||||
*/
|
||||
int addIdleTimeout(int msec);
|
||||
|
||||
#if __has_include(<chrono>)
|
||||
/**
|
||||
* Convenience overload supporting C++ chrono types. May also be used with chrono literals.
|
||||
* @since 5.83
|
||||
*/
|
||||
int addIdleTimeout(std::chrono::milliseconds msec)
|
||||
{
|
||||
return addIdleTimeout(int(msec.count()));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Stops catching the idle timeout identified by the token \c identifier,
|
||||
* if it was registered earlier with addIdleTimeout.
|
||||
* Otherwise does nothing.
|
||||
*
|
||||
* @param identifier the token returned from addIdleTimeout of the timeout you want to stop listening to
|
||||
*/
|
||||
void removeIdleTimeout(int identifier);
|
||||
|
||||
/**
|
||||
* Stops catching every set timeout (if any). This means that after calling this method, the signal
|
||||
* \link timeoutReached \endlink won't be called again until you will add another timeout
|
||||
*
|
||||
* @see timeoutReached
|
||||
* @see addIdleTimeout
|
||||
*/
|
||||
void removeAllIdleTimeouts();
|
||||
|
||||
/**
|
||||
* Catches the next resume from idle event. This means that whenever user activity will be registered, or
|
||||
* \link simulateUserActivity \endlink is called, the signal \link resumingFromIdle \endlink will be triggered.
|
||||
* <p>
|
||||
* Please note that this method will trigger the signal just for the very first resume event after the call:
|
||||
* this means you explicitly have to request to track every single resume event you are interested in.
|
||||
*
|
||||
* @note This behavior is due to the fact that a resume event happens whenever the user sends an input to the
|
||||
* system. This would lead to a massive amount of signals being delivered when the PC is being used.
|
||||
* Moreover, you are usually interested in catching just significant resume events, such as the ones after
|
||||
* a significant period of inactivity. For tracking user input, you can use the more efficient methods provided
|
||||
* by Qt. The purpose of this library is just monitoring the activity of the user.
|
||||
*
|
||||
* @see resumingFromIdle
|
||||
* @see simulateUserActivity
|
||||
*
|
||||
*/
|
||||
void catchNextResumeEvent();
|
||||
|
||||
/**
|
||||
* Stops listening for resume event. This function serves for canceling \c catchNextResumeEvent, as it
|
||||
* will have effect just when \c catchNextResumeEvent has been called and \c resumingFromIdle not
|
||||
* yet triggered
|
||||
*
|
||||
* @see resumingFromIdle
|
||||
* @see catchNextResumeEvent
|
||||
*
|
||||
*/
|
||||
void stopCatchingResumeEvent();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Triggered, if KIdleTime is catching resume events, when the system resumes from an idle state. This means
|
||||
* that either \link simulateUserActivity \endlink was called or the user sent an input to the system.
|
||||
*
|
||||
* @see catchNextResumeEvent
|
||||
*/
|
||||
void resumingFromIdle();
|
||||
|
||||
/**
|
||||
* Triggered when the system has been idle for x milliseconds, identified by the previously set
|
||||
* timeout.
|
||||
*
|
||||
* This signal is triggered whenever each timeout previously registered with addIdleTimeout(int)
|
||||
* is reached. It is guaranteed that \p msec will exactly correspond to the identified timeout.
|
||||
*
|
||||
* @param identifier the identifier of the timeout the system has reached
|
||||
* @param msec the time, in milliseconds, the system has been idle for
|
||||
*
|
||||
* @see addIdleTimeout
|
||||
* @see removeIdleTimeout
|
||||
*/
|
||||
void timeoutReached(int identifier, int msec); // clazy:exclude=overloaded-signal
|
||||
|
||||
private:
|
||||
KIDLETIME_NO_EXPORT KIdleTime();
|
||||
|
||||
std::unique_ptr<KIdleTimePrivate> const d_ptr;
|
||||
};
|
||||
|
||||
#endif /* KIDLETIME_H */
|
||||
@@ -0,0 +1,147 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "kwindowbasedidletimepoller_p.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QTimer>
|
||||
#include <QWindow>
|
||||
|
||||
KWindowBasedIdleTimePoller::KWindowBasedIdleTimePoller(QObject *parent)
|
||||
: KAbstractIdleTimePoller(parent)
|
||||
{
|
||||
}
|
||||
|
||||
KWindowBasedIdleTimePoller::~KWindowBasedIdleTimePoller()
|
||||
{
|
||||
}
|
||||
|
||||
bool KWindowBasedIdleTimePoller::isAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KWindowBasedIdleTimePoller::setUpPoller()
|
||||
{
|
||||
m_pollTimer = new QTimer(this);
|
||||
|
||||
// setup idle timer, with some smart polling
|
||||
connect(m_pollTimer, &QTimer::timeout, this, &KWindowBasedIdleTimePoller::poll);
|
||||
|
||||
m_grabber = new QWindow();
|
||||
m_grabber->setFlag(Qt::X11BypassWindowManagerHint);
|
||||
m_grabber->setPosition(-1000, -1000);
|
||||
m_grabber->installEventFilter(this);
|
||||
m_grabber->setObjectName(QStringLiteral("KIdleGrabberWidget"));
|
||||
|
||||
return additionalSetUp();
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::unloadPoller()
|
||||
{
|
||||
m_pollTimer->deleteLater();
|
||||
m_grabber->deleteLater();
|
||||
}
|
||||
|
||||
QList<int> KWindowBasedIdleTimePoller::timeouts() const
|
||||
{
|
||||
return m_timeouts;
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::addTimeout(int nextTimeout)
|
||||
{
|
||||
m_timeouts.append(nextTimeout);
|
||||
poll();
|
||||
}
|
||||
|
||||
bool KWindowBasedIdleTimePoller::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (object == m_grabber && (event->type() == QEvent::MouseMove || event->type() == QEvent::KeyPress)) {
|
||||
detectedActivity();
|
||||
return true;
|
||||
} else if (object != m_grabber) {
|
||||
// If it's not the grabber, fallback to default event filter
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, simply ignore it
|
||||
return false;
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::waitForActivity()
|
||||
{
|
||||
m_grabber->show();
|
||||
m_grabber->setMouseGrabEnabled(true);
|
||||
m_grabber->setKeyboardGrabEnabled(true);
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::detectedActivity()
|
||||
{
|
||||
stopCatchingIdleEvents();
|
||||
Q_EMIT resumingFromIdle();
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::releaseInputLock()
|
||||
{
|
||||
m_grabber->setMouseGrabEnabled(false);
|
||||
m_grabber->setKeyboardGrabEnabled(false);
|
||||
m_grabber->hide();
|
||||
}
|
||||
|
||||
int KWindowBasedIdleTimePoller::poll()
|
||||
{
|
||||
int idle = getIdleTime();
|
||||
|
||||
// Check if we reached a timeout..
|
||||
for (int timeOut : std::as_const(m_timeouts)) {
|
||||
if ((timeOut - idle < 300 && timeOut >= idle) || (idle - timeOut < 300 && idle > timeOut)) {
|
||||
// Bingo!
|
||||
Q_EMIT timeoutReached(timeOut);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's check the timer now!
|
||||
int mintime = 0;
|
||||
|
||||
for (int i : std::as_const(m_timeouts)) {
|
||||
if (i > idle && (i < mintime || mintime == 0)) {
|
||||
mintime = i;
|
||||
}
|
||||
}
|
||||
|
||||
// qDebug() << "mintime " << mintime << "idle " << idle;
|
||||
|
||||
if (mintime != 0) {
|
||||
m_pollTimer->start(mintime - idle);
|
||||
} else {
|
||||
m_pollTimer->stop();
|
||||
}
|
||||
|
||||
return idle;
|
||||
}
|
||||
|
||||
int KWindowBasedIdleTimePoller::forcePollRequest()
|
||||
{
|
||||
return poll();
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::removeTimeout(int timeout)
|
||||
{
|
||||
m_timeouts.removeOne(timeout);
|
||||
poll();
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::catchIdleEvent()
|
||||
{
|
||||
waitForActivity();
|
||||
}
|
||||
|
||||
void KWindowBasedIdleTimePoller::stopCatchingIdleEvents()
|
||||
{
|
||||
releaseInputLock();
|
||||
}
|
||||
|
||||
#include "moc_kwindowbasedidletimepoller_p.cpp"
|
||||
@@ -0,0 +1,59 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef KWINDOWBASEDIDLETIMEPOLLER_P_H
|
||||
#define KWINDOWBASEDIDLETIMEPOLLER_P_H
|
||||
|
||||
#include <kidletime_export.h>
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
|
||||
class QTimer;
|
||||
class QEvent;
|
||||
class QWindow;
|
||||
|
||||
class KIDLETIME_EXPORT KWindowBasedIdleTimePoller : public KAbstractIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit KWindowBasedIdleTimePoller(QObject *parent = nullptr);
|
||||
~KWindowBasedIdleTimePoller() override;
|
||||
|
||||
bool isAvailable() override;
|
||||
bool setUpPoller() override;
|
||||
void unloadPoller() override;
|
||||
|
||||
QList<int> timeouts() const override;
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void addTimeout(int nextTimeout) override;
|
||||
void removeTimeout(int nextTimeout) override;
|
||||
|
||||
int forcePollRequest() override;
|
||||
void catchIdleEvent() override;
|
||||
void stopCatchingIdleEvents() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
int poll();
|
||||
virtual int getIdleTime() = 0;
|
||||
void detectedActivity();
|
||||
void waitForActivity();
|
||||
void releaseInputLock();
|
||||
|
||||
private:
|
||||
virtual bool additionalSetUp() = 0;
|
||||
|
||||
private:
|
||||
QTimer *m_pollTimer;
|
||||
QWindow *m_grabber;
|
||||
QList<int> m_timeouts;
|
||||
};
|
||||
|
||||
#endif /* KWINDOWBASEDIDLETIMEPOLLER_P_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
if(APPLE)
|
||||
add_subdirectory(osx)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_subdirectory(windows)
|
||||
endif()
|
||||
|
||||
if(WITH_X11)
|
||||
if(HAVE_XSCREENSAVER)
|
||||
add_subdirectory(xscreensaver)
|
||||
endif()
|
||||
if(HAVE_XSYNC)
|
||||
add_subdirectory(xsync)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_WAYLAND)
|
||||
add_subdirectory(wayland)
|
||||
endif()
|
||||
@@ -0,0 +1,17 @@
|
||||
add_library(KF6IdleTimeOsxPlugin MODULE)
|
||||
|
||||
target_sources(KF6IdleTimeOsxPlugin PRIVATE
|
||||
macpoller.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(KF6IdleTimeOsxPlugin
|
||||
KF6IdleTime
|
||||
"-framework CoreFoundation -framework Carbon"
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KF6IdleTimeOsxPlugin
|
||||
DESTINATION
|
||||
${KDE_INSTALL_PLUGINDIR}/kf6/kidletime/
|
||||
)
|
||||
@@ -0,0 +1,217 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
* SPDX-FileCopyrightText: 2003 Tarkvara Design Inc. (from KVIrc source code)
|
||||
* SPDX-FileCopyrightText: 2008 Roman Jarosz <kedgedev at centrum.cz>
|
||||
* SPDX-FileCopyrightText: 2008 the Kopete developers <kopete-devel at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "macpoller.h"
|
||||
|
||||
// Why does Apple have to make this so complicated?
|
||||
static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr)
|
||||
{
|
||||
OSStatus err;
|
||||
FSRef frameworksFolderRef;
|
||||
CFURLRef baseURL;
|
||||
CFURLRef bundleURL;
|
||||
|
||||
if (bundlePtr == nil) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*bundlePtr = nil;
|
||||
|
||||
baseURL = nil;
|
||||
bundleURL = nil;
|
||||
|
||||
err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
|
||||
if (err == noErr) {
|
||||
baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
|
||||
if (baseURL == nil) {
|
||||
err = coreFoundationUnknownErr;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == noErr) {
|
||||
bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false);
|
||||
if (bundleURL == nil) {
|
||||
err = coreFoundationUnknownErr;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == noErr) {
|
||||
*bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
|
||||
if (*bundlePtr == nil) {
|
||||
err = coreFoundationUnknownErr;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == noErr) {
|
||||
if (!CFBundleLoadExecutable(*bundlePtr)) {
|
||||
err = coreFoundationUnknownErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
if (err != noErr && *bundlePtr != nil) {
|
||||
CFRelease(*bundlePtr);
|
||||
*bundlePtr = nil;
|
||||
}
|
||||
|
||||
if (bundleURL != nil) {
|
||||
CFRelease(bundleURL);
|
||||
}
|
||||
|
||||
if (baseURL != nil) {
|
||||
CFRelease(baseURL);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
pascal void MacPoller::IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void *inUserData)
|
||||
{
|
||||
Q_ASSERT(inUserData);
|
||||
switch (inState) {
|
||||
case kEventLoopIdleTimerStarted:
|
||||
case kEventLoopIdleTimerStopped:
|
||||
// Get invoked with this constant at the start of the idle period,
|
||||
// or whenever user activity cancels the idle.
|
||||
((MacPoller *)inUserData)->m_secondsIdle = 0;
|
||||
((MacPoller *)inUserData)->triggerResume();
|
||||
break;
|
||||
case kEventLoopIdleTimerIdling:
|
||||
// Called every time the timer fires (i.e. every second).
|
||||
((MacPoller *)inUserData)->m_secondsIdle++;
|
||||
((MacPoller *)inUserData)->poll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Typedef for the function we're getting back from CFBundleGetFunctionPointerForName.
|
||||
typedef OSStatus (*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop,
|
||||
EventTimerInterval inFireDelay,
|
||||
EventTimerInterval inInterval,
|
||||
EventLoopIdleTimerUPP inTimerProc,
|
||||
void *inTimerData,
|
||||
EventLoopTimerRef *outTimer);
|
||||
|
||||
MacPoller::MacPoller(QObject *parent)
|
||||
: KAbstractIdleTimePoller(parent)
|
||||
, m_timerRef(0)
|
||||
, m_secondsIdle(0)
|
||||
, m_catch(false)
|
||||
{
|
||||
}
|
||||
|
||||
MacPoller::~MacPoller()
|
||||
{
|
||||
}
|
||||
|
||||
void MacPoller::unloadPoller()
|
||||
{
|
||||
RemoveEventLoopTimer(m_timerRef);
|
||||
}
|
||||
|
||||
bool MacPoller::isAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacPoller::setUpPoller()
|
||||
{
|
||||
// May already be init'ed.
|
||||
if (m_timerRef) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// According to the docs, InstallEventLoopIdleTimer is new in 10.2.
|
||||
// According to the headers, it has been around since 10.0.
|
||||
// One of them is lying. We'll play it safe and weak-link the function.
|
||||
|
||||
// Load the "Carbon.framework" bundle.
|
||||
CFBundleRef carbonBundle;
|
||||
|
||||
if (LoadFrameworkBundle(CFSTR("Carbon.framework"), &carbonBundle) != noErr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the Mach-O function pointers for the routine we will be using.
|
||||
InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer =
|
||||
(InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName(carbonBundle, CFSTR("InstallEventLoopIdleTimer"));
|
||||
|
||||
if (myInstallEventLoopIdleTimer == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP(IdleTimerAction);
|
||||
if ((*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, this, &m_timerRef)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<int> MacPoller::timeouts() const
|
||||
{
|
||||
return m_timeouts;
|
||||
}
|
||||
|
||||
void MacPoller::addTimeout(int nextTimeout)
|
||||
{
|
||||
m_timeouts.append(nextTimeout);
|
||||
poll();
|
||||
}
|
||||
|
||||
int MacPoller::poll()
|
||||
{
|
||||
int idle = m_secondsIdle * 1000;
|
||||
|
||||
// Check if we reached a timeout..
|
||||
for (int i : std::as_const(m_timeouts)) {
|
||||
if ((i - idle < 1000 && i > idle) || (idle - i < 1000 && idle > i)) {
|
||||
// Bingo!
|
||||
Q_EMIT timeoutReached(i);
|
||||
}
|
||||
}
|
||||
|
||||
return idle;
|
||||
}
|
||||
|
||||
int MacPoller::forcePollRequest()
|
||||
{
|
||||
return poll();
|
||||
}
|
||||
|
||||
void MacPoller::removeTimeout(int timeout)
|
||||
{
|
||||
m_timeouts.removeOne(timeout);
|
||||
poll();
|
||||
}
|
||||
|
||||
void MacPoller::catchIdleEvent()
|
||||
{
|
||||
m_catch = true;
|
||||
}
|
||||
|
||||
void MacPoller::stopCatchingIdleEvents()
|
||||
{
|
||||
m_catch = false;
|
||||
}
|
||||
|
||||
void MacPoller::triggerResume()
|
||||
{
|
||||
if (m_catch) {
|
||||
Q_EMIT resumingFromIdle();
|
||||
stopCatchingIdleEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void MacPoller::simulateUserActivity()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
#include "moc_macpoller.cpp"
|
||||
@@ -0,0 +1,50 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef MACPOLLER_H
|
||||
#define MACPOLLER_H
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
class MacPoller : public KAbstractIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID KAbstractIdleTimePoller_iid FILE "osx.json")
|
||||
Q_INTERFACES(KAbstractIdleTimePoller)
|
||||
|
||||
public:
|
||||
MacPoller(QObject *parent = 0);
|
||||
virtual ~MacPoller();
|
||||
|
||||
bool isAvailable();
|
||||
bool setUpPoller();
|
||||
void unloadPoller();
|
||||
|
||||
static pascal void IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void *inUserData);
|
||||
|
||||
public Q_SLOTS:
|
||||
void addTimeout(int nextTimeout);
|
||||
void removeTimeout(int nextTimeout);
|
||||
QList<int> timeouts() const;
|
||||
int forcePollRequest();
|
||||
void catchIdleEvent();
|
||||
void stopCatchingIdleEvents();
|
||||
void simulateUserActivity();
|
||||
void triggerResume();
|
||||
|
||||
private Q_SLOTS:
|
||||
int poll();
|
||||
|
||||
private:
|
||||
QList<int> m_timeouts;
|
||||
EventLoopTimerRef m_timerRef;
|
||||
int m_secondsIdle;
|
||||
bool m_catch;
|
||||
};
|
||||
|
||||
#endif /* MACPOLLER_H */
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"platforms": ["cocoa"]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
add_library(KF6IdleTimeWaylandPlugin MODULE)
|
||||
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL "6.8.0")
|
||||
set(private_code_option "PRIVATE_CODE")
|
||||
endif()
|
||||
qt6_generate_wayland_protocol_client_sources(KF6IdleTimeWaylandPlugin FILES
|
||||
${PLASMA_WAYLAND_PROTOCOLS_DIR}/idle.xml
|
||||
${WaylandProtocols_DATADIR}/staging/ext-idle-notify/ext-idle-notify-v1.xml
|
||||
${private_code_option}
|
||||
)
|
||||
|
||||
target_sources(KF6IdleTimeWaylandPlugin PRIVATE poller.cpp ${idletime_plugin_SRCS})
|
||||
|
||||
target_link_libraries(KF6IdleTimeWaylandPlugin
|
||||
KF6::IdleTime
|
||||
Qt6::WaylandClient
|
||||
Wayland::Client
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KF6IdleTimeWaylandPlugin
|
||||
DESTINATION
|
||||
${KDE_INSTALL_PLUGINDIR}/kf6/org.kde.kidletime.platforms/
|
||||
)
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "poller.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QLoggingCategory>
|
||||
#include <QWaylandClientExtensionTemplate>
|
||||
#include <QtWaylandClientVersion>
|
||||
|
||||
#include "qwayland-ext-idle-notify-v1.h"
|
||||
#include "qwayland-idle.h"
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(POLLER)
|
||||
Q_LOGGING_CATEGORY(POLLER, "kf5idletime_wayland")
|
||||
|
||||
/*
|
||||
* Porting notes:
|
||||
* org_kde_kwin_idle refers to an early specific idle timeout protocol
|
||||
* the version ext_idle refers to an upstream stable protocol
|
||||
*
|
||||
* Pragmattically they're both the same, but we have to have two implementations for a while
|
||||
*
|
||||
* When a suitable amount of time passes (Plasma 5.24 being EOL) drop IdleTimeoutKwin and drop IdleManagerKwin as well as merge the abstract IdleTimeout class into the real implementation
|
||||
*/
|
||||
|
||||
class IdleTimeout : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
IdleTimeout() = default;
|
||||
Q_SIGNALS:
|
||||
void idle();
|
||||
void resumeFromIdle();
|
||||
};
|
||||
|
||||
class IdleTimeoutKwin : public IdleTimeout, public QtWayland::org_kde_kwin_idle_timeout
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
IdleTimeoutKwin(struct ::org_kde_kwin_idle_timeout *object)
|
||||
: IdleTimeout()
|
||||
, QtWayland::org_kde_kwin_idle_timeout(object)
|
||||
{}
|
||||
|
||||
~IdleTimeoutKwin()
|
||||
{
|
||||
if (qGuiApp) {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void org_kde_kwin_idle_timeout_idle() override {
|
||||
Q_EMIT idle();
|
||||
}
|
||||
void org_kde_kwin_idle_timeout_resumed() override {
|
||||
Q_EMIT resumeFromIdle();
|
||||
}
|
||||
};
|
||||
|
||||
class IdleTimeoutExt : public IdleTimeout, public QtWayland::ext_idle_notification_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
IdleTimeoutExt(struct ::ext_idle_notification_v1 *object)
|
||||
: IdleTimeout()
|
||||
, QtWayland::ext_idle_notification_v1(object)
|
||||
{
|
||||
}
|
||||
|
||||
~IdleTimeoutExt()
|
||||
{
|
||||
if (qGuiApp) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void ext_idle_notification_v1_idled() override
|
||||
{
|
||||
Q_EMIT idle();
|
||||
}
|
||||
void ext_idle_notification_v1_resumed() override
|
||||
{
|
||||
Q_EMIT resumeFromIdle();
|
||||
}
|
||||
};
|
||||
|
||||
class IdleManagerKwin : public QWaylandClientExtensionTemplate<IdleManagerKwin>, public QtWayland::org_kde_kwin_idle
|
||||
{
|
||||
public:
|
||||
IdleManagerKwin()
|
||||
: QWaylandClientExtensionTemplate<IdleManagerKwin>(1)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
};
|
||||
|
||||
class IdleManagerExt : public QWaylandClientExtensionTemplate<IdleManagerExt>, public QtWayland::ext_idle_notifier_v1
|
||||
{
|
||||
public:
|
||||
IdleManagerExt()
|
||||
: QWaylandClientExtensionTemplate<IdleManagerExt>(1)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
~IdleManagerExt()
|
||||
{
|
||||
if (qGuiApp && isActive()) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Poller::Poller(QObject *parent)
|
||||
: KAbstractIdleTimePoller(parent)
|
||||
, m_idleManagerKwin(new IdleManagerKwin)
|
||||
, m_idleManagerExt(new IdleManagerExt)
|
||||
{
|
||||
}
|
||||
|
||||
Poller::~Poller() = default;
|
||||
|
||||
bool Poller::isAvailable()
|
||||
{
|
||||
return m_idleManagerKwin->isActive() || m_idleManagerExt->isActive();
|
||||
}
|
||||
|
||||
void Poller::addTimeout(int nextTimeout)
|
||||
{
|
||||
if (m_timeouts.contains(nextTimeout)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto timeout = createTimeout(nextTimeout);
|
||||
if (!timeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(timeout, &IdleTimeout::idle, this, [this, nextTimeout] {
|
||||
Q_EMIT timeoutReached(nextTimeout);
|
||||
});
|
||||
connect(timeout, &IdleTimeout::resumeFromIdle, this, &Poller::resumingFromIdle);
|
||||
m_timeouts.insert(nextTimeout, QSharedPointer<IdleTimeout>(timeout));
|
||||
}
|
||||
|
||||
void Poller::removeTimeout(int nextTimeout)
|
||||
{
|
||||
m_timeouts.remove(nextTimeout);
|
||||
}
|
||||
|
||||
QList<int> Poller::timeouts() const
|
||||
{
|
||||
return QList<int>();
|
||||
}
|
||||
|
||||
void Poller::catchIdleEvent()
|
||||
{
|
||||
if (m_catchResumeTimeout) {
|
||||
// already setup
|
||||
return;
|
||||
}
|
||||
if (!isAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_catchResumeTimeout.reset(createTimeout(0));
|
||||
if (!m_catchResumeTimeout) {
|
||||
return;
|
||||
}
|
||||
connect(m_catchResumeTimeout.get(), &IdleTimeout::resumeFromIdle, this, [this] {
|
||||
stopCatchingIdleEvents();
|
||||
Q_EMIT resumingFromIdle();
|
||||
});
|
||||
}
|
||||
|
||||
void Poller::stopCatchingIdleEvents()
|
||||
{
|
||||
m_catchResumeTimeout.reset();
|
||||
}
|
||||
|
||||
int Poller::forcePollRequest()
|
||||
{
|
||||
qCWarning(POLLER) << "This plugin does not support polling idle time";
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Poller::simulateUserActivity()
|
||||
{
|
||||
}
|
||||
|
||||
IdleTimeout* Poller::createTimeout(int timeout)
|
||||
{
|
||||
auto waylandApp = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
|
||||
if (!waylandApp) {
|
||||
return nullptr;
|
||||
}
|
||||
auto seat = waylandApp->seat();
|
||||
|
||||
if (!seat) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (m_idleManagerExt->isActive()) {
|
||||
return new IdleTimeoutExt(m_idleManagerExt->get_idle_notification(timeout, seat));
|
||||
}
|
||||
if (m_idleManagerKwin->isActive()) {
|
||||
return new IdleTimeoutKwin(m_idleManagerKwin->get_idle_timeout(seat, timeout));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#include "moc_poller.cpp"
|
||||
#include "poller.moc"
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <memory>
|
||||
|
||||
class IdleManagerKwin;
|
||||
class IdleManagerExt;
|
||||
|
||||
class IdleTimeout;
|
||||
|
||||
class Poller : public KAbstractIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID KAbstractIdleTimePoller_iid FILE "wayland.json")
|
||||
Q_INTERFACES(KAbstractIdleTimePoller)
|
||||
|
||||
public:
|
||||
explicit Poller(QObject *parent = nullptr);
|
||||
~Poller() override;
|
||||
|
||||
bool isAvailable() override;
|
||||
bool setUpPoller() override {
|
||||
return true;
|
||||
}
|
||||
void unloadPoller() override {}
|
||||
|
||||
public Q_SLOTS:
|
||||
void addTimeout(int nextTimeout) override;
|
||||
void removeTimeout(int nextTimeout) override;
|
||||
QList<int> timeouts() const override;
|
||||
int forcePollRequest() override;
|
||||
void catchIdleEvent() override;
|
||||
void stopCatchingIdleEvents() override;
|
||||
void simulateUserActivity() override;
|
||||
|
||||
private:
|
||||
bool initWayland();
|
||||
IdleTimeout* createTimeout(int timeout);
|
||||
|
||||
QScopedPointer<IdleManagerKwin> m_idleManagerKwin;
|
||||
QScopedPointer<IdleManagerExt> m_idleManagerExt;
|
||||
QHash<int, QSharedPointer<IdleTimeout>> m_timeouts;
|
||||
QScopedPointer<IdleTimeout> m_catchResumeTimeout;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"platforms": ["wayland", "wayland-egl"]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
add_library(KF6IdleTimeWindowsPlugin MODULE)
|
||||
|
||||
target_sources(KF6IdleTimeWindowsPlugin PRIVATE
|
||||
windowspoller.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(KF6IdleTimeWindowsPlugin
|
||||
KF6IdleTime
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KF6IdleTimeWindowsPlugin
|
||||
DESTINATION
|
||||
${KDE_INSTALL_PLUGINDIR}/kf6/org.kde.kidletime.platforms/
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"platforms": ["windows"]
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "windowspoller.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
WindowsPoller::WindowsPoller(QObject *parent)
|
||||
: KWindowBasedIdleTimePoller(parent)
|
||||
{
|
||||
}
|
||||
|
||||
WindowsPoller::~WindowsPoller()
|
||||
{
|
||||
}
|
||||
|
||||
int WindowsPoller::getIdleTime()
|
||||
{
|
||||
#ifndef _WIN32_WCE
|
||||
int idle = 0;
|
||||
|
||||
LASTINPUTINFO lii;
|
||||
memset(&lii, 0, sizeof(lii));
|
||||
|
||||
lii.cbSize = sizeof(lii);
|
||||
|
||||
BOOL ok = GetLastInputInfo(&lii);
|
||||
if (ok) {
|
||||
idle = GetTickCount() - lii.dwTime;
|
||||
}
|
||||
|
||||
return idle;
|
||||
#else
|
||||
return GetIdleTime();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WindowsPoller::additionalSetUp()
|
||||
{
|
||||
m_idleTimer = new QTimer(this);
|
||||
connect(m_idleTimer, &QTimer::timeout, this, &WindowsPoller::checkForIdle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowsPoller::simulateUserActivity()
|
||||
{
|
||||
int width = GetSystemMetrics(SM_CXSCREEN);
|
||||
int height = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
int x = (int)100 * 65536 / width;
|
||||
int y = (int)100 * 65536 / height;
|
||||
|
||||
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, NULL, NULL);
|
||||
}
|
||||
|
||||
void WindowsPoller::catchIdleEvent()
|
||||
{
|
||||
m_idleTimer->start(800);
|
||||
}
|
||||
|
||||
void WindowsPoller::stopCatchingIdleEvents()
|
||||
{
|
||||
m_idleTimer->stop();
|
||||
}
|
||||
|
||||
void WindowsPoller::checkForIdle()
|
||||
{
|
||||
if (getIdleTime() < 1000) {
|
||||
stopCatchingIdleEvents();
|
||||
Q_EMIT resumingFromIdle();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_windowspoller.cpp"
|
||||
@@ -0,0 +1,40 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef WINDOWSPOLLER_H
|
||||
#define WINDOWSPOLLER_H
|
||||
|
||||
#include "kwindowbasedidletimepoller_p.h"
|
||||
|
||||
class QTimer;
|
||||
|
||||
class WindowsPoller : public KWindowBasedIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID KAbstractIdleTimePoller_iid FILE "windows.json")
|
||||
Q_INTERFACES(KAbstractIdleTimePoller)
|
||||
|
||||
public:
|
||||
WindowsPoller(QObject *parent = 0);
|
||||
virtual ~WindowsPoller();
|
||||
|
||||
public Q_SLOTS:
|
||||
void simulateUserActivity();
|
||||
void catchIdleEvent();
|
||||
void stopCatchingIdleEvents();
|
||||
|
||||
private:
|
||||
bool additionalSetUp();
|
||||
|
||||
private Q_SLOTS:
|
||||
int getIdleTime();
|
||||
void checkForIdle();
|
||||
|
||||
private:
|
||||
QTimer *m_idleTimer;
|
||||
};
|
||||
|
||||
#endif /* WINDOWSPOLLER_H */
|
||||
@@ -0,0 +1,24 @@
|
||||
add_library(KF6IdleTimeXcbPlugin1 MODULE)
|
||||
|
||||
set(xscreensaver_plugin_dbus_SRCS)
|
||||
qt_add_dbus_interface(xscreensaver_plugin_dbus_SRCS org.freedesktop.ScreenSaver.xml screensaver_interface)
|
||||
|
||||
target_sources(KF6IdleTimeXcbPlugin1 PRIVATE
|
||||
xscreensaverbasedpoller.cpp
|
||||
${xscreensaver_plugin_dbus_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(KF6IdleTimeXcbPlugin1
|
||||
KF6IdleTime
|
||||
Qt6::DBus
|
||||
Qt6::Gui
|
||||
${X11_LIBRARIES}
|
||||
${X11_Xscreensaver_LIB}
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KF6IdleTimeXcbPlugin1
|
||||
DESTINATION
|
||||
${KDE_INSTALL_PLUGINDIR}/kf6/org.kde.kidletime.platforms/
|
||||
)
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.freedesktop.ScreenSaver">
|
||||
<signal name="ActiveChanged">
|
||||
<arg type="b"/>
|
||||
</signal>
|
||||
<method name="Lock">
|
||||
</method>
|
||||
<method name="SimulateUserActivity">
|
||||
</method>
|
||||
<method name="GetActive">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="GetActiveTime">
|
||||
<arg name="seconds" type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="GetSessionIdleTime">
|
||||
<arg name="seconds" type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="SetActive">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="e" type="b" direction="in"/>
|
||||
</method>
|
||||
<method name="Inhibit">
|
||||
<arg name="application_name" type="s" direction="in"/>
|
||||
<arg name="reason_for_inhibit" type="s" direction="in"/>
|
||||
<arg name="cookie" type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="UnInhibit">
|
||||
<arg name="cookie" type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="Throttle">
|
||||
<arg name="application_name" type="s" direction="in"/>
|
||||
<arg name="reason_for_inhibit" type="s" direction="in"/>
|
||||
<arg name="cookie" type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="UnThrottle">
|
||||
<arg name="cookie" type="u" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"platforms": ["xcb"]
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "xscreensaverbasedpoller.h"
|
||||
|
||||
#include <config-kidletime.h>
|
||||
|
||||
#include <QGuiApplication>
|
||||
|
||||
// sourcing the moc file before the Xlib include,
|
||||
// whose defines like "Bool" break Qt names
|
||||
#include "moc_xscreensaverbasedpoller.cpp"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
|
||||
static Display *display()
|
||||
{
|
||||
return qGuiApp->nativeInterface<QNativeInterface::QX11Application>()->display();
|
||||
}
|
||||
|
||||
XScreensaverBasedPoller::XScreensaverBasedPoller(QObject *parent)
|
||||
: KWindowBasedIdleTimePoller(parent)
|
||||
, m_screenSaverIface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
XScreensaverBasedPoller::~XScreensaverBasedPoller()
|
||||
{
|
||||
}
|
||||
|
||||
bool XScreensaverBasedPoller::additionalSetUp()
|
||||
{
|
||||
m_screenSaverIface = new OrgFreedesktopScreenSaverInterface(QLatin1String("org.freedesktop.ScreenSaver"),
|
||||
QLatin1String("/ScreenSaver"),
|
||||
QDBusConnection::sessionBus(),
|
||||
this);
|
||||
|
||||
connect(m_screenSaverIface, &OrgFreedesktopScreenSaverInterface::ActiveChanged, this, &XScreensaverBasedPoller::screensaverActivated);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XScreensaverBasedPoller::screensaverActivated(bool activated)
|
||||
{
|
||||
// We care only if it has been disactivated
|
||||
|
||||
if (!activated) {
|
||||
m_screenSaverIface->SimulateUserActivity();
|
||||
Q_EMIT resumingFromIdle();
|
||||
}
|
||||
}
|
||||
|
||||
int XScreensaverBasedPoller::getIdleTime()
|
||||
{
|
||||
XScreenSaverInfo *mitInfo = nullptr;
|
||||
mitInfo = XScreenSaverAllocInfo();
|
||||
XScreenSaverQueryInfo(display(), DefaultRootWindow(display()), mitInfo);
|
||||
int ret = mitInfo->idle;
|
||||
XFree(mitInfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void XScreensaverBasedPoller::simulateUserActivity()
|
||||
{
|
||||
stopCatchingIdleEvents();
|
||||
XResetScreenSaver(display());
|
||||
XFlush(display());
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef XSCREENSAVERBASEDPOLLER_H
|
||||
#define XSCREENSAVERBASEDPOLLER_H
|
||||
|
||||
#include "kwindowbasedidletimepoller_p.h"
|
||||
|
||||
#include "screensaver_interface.h"
|
||||
|
||||
class XScreensaverBasedPoller : public KWindowBasedIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID KAbstractIdleTimePoller_iid FILE "xcb.json")
|
||||
Q_INTERFACES(KAbstractIdleTimePoller)
|
||||
|
||||
public:
|
||||
explicit XScreensaverBasedPoller(QObject *parent = nullptr);
|
||||
~XScreensaverBasedPoller() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void simulateUserActivity() override;
|
||||
|
||||
private:
|
||||
bool additionalSetUp() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void screensaverActivated(bool activated);
|
||||
int getIdleTime() override;
|
||||
|
||||
private:
|
||||
OrgFreedesktopScreenSaverInterface *m_screenSaverIface;
|
||||
};
|
||||
|
||||
#endif /* XSCREENSAVERBASEDPOLLER_H_ */
|
||||
@@ -0,0 +1,38 @@
|
||||
add_library(KF6IdleTimeXcbPlugin0 MODULE)
|
||||
|
||||
target_include_directories(KF6IdleTimeXcbPlugin0
|
||||
PRIVATE
|
||||
${XCB_XCB_INCLUDE_DIR}
|
||||
${XCB_SYNC_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_sources(KF6IdleTimeXcbPlugin0 PRIVATE
|
||||
xsyncbasedpoller.cpp
|
||||
../../logging.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(KF6IdleTimeXcbPlugin0
|
||||
HEADER xsync_logging.h
|
||||
IDENTIFIER KIDLETIME_XSYNC_PLUGIN
|
||||
CATEGORY_NAME kf.idletime.xsync
|
||||
OLD_CATEGORY_NAMES org.kde.kf5.idletime.xsync
|
||||
DESCRIPTION "xsync plugin"
|
||||
EXPORT KIDLETIME
|
||||
)
|
||||
|
||||
target_link_libraries(KF6IdleTimeXcbPlugin0
|
||||
KF6IdleTime
|
||||
Qt6::Gui
|
||||
XCB::XCB
|
||||
XCB::SYNC
|
||||
X11::XCB
|
||||
${X11_LIBRARIES}
|
||||
${X11_Xext_LIB}
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KF6IdleTimeXcbPlugin0
|
||||
DESTINATION
|
||||
${KDE_INSTALL_PLUGINDIR}/kf6/org.kde.kidletime.platforms/
|
||||
)
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
//#ifdef don't do this, this file is supposed to be included
|
||||
//#define multiple times
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
/* Usage:
|
||||
|
||||
If you get compile errors caused by X11 includes (the line
|
||||
where first error appears contains word like None, Unsorted,
|
||||
Below, etc.), put #include <fixx11h.h> in the .cpp file
|
||||
(not .h file!) between the place where X11 headers are
|
||||
included and the place where the file with compile
|
||||
error is included (or the place where the compile error
|
||||
in the .cpp file occurs).
|
||||
|
||||
This file remaps X11 #defines to const variables or
|
||||
inline functions. The side effect may be that these
|
||||
symbols may now refer to different variables
|
||||
(e.g. if X11 #defined NoButton, after this file
|
||||
is included NoButton would no longer be X11's
|
||||
NoButton, but Qt::NoButton instead). At this time,
|
||||
there's no conflict known that could cause problems.
|
||||
|
||||
The original X11 symbols are still accessible
|
||||
(e.g. for None) as X::None, XNone, and also still
|
||||
None, unless name lookup finds different None
|
||||
first (in the current class, etc.)
|
||||
|
||||
Use 'Unsorted', 'Bool' and 'index' as templates.
|
||||
|
||||
*/
|
||||
|
||||
namespace X
|
||||
{
|
||||
// template --->
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Unsorted
|
||||
#ifndef FIXX11H_Unsorted
|
||||
#define FIXX11H_Unsorted
|
||||
const int XUnsorted = Unsorted;
|
||||
#undef Unsorted
|
||||
const int Unsorted = XUnsorted;
|
||||
#endif
|
||||
#undef Unsorted
|
||||
#endif
|
||||
// template <---
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef None
|
||||
#ifndef FIXX11H_None
|
||||
#define FIXX11H_None
|
||||
const XID XNone = None;
|
||||
#undef None
|
||||
const XID None = XNone;
|
||||
#endif
|
||||
#undef None
|
||||
#endif
|
||||
|
||||
// template --->
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Bool
|
||||
#ifndef FIXX11H_Bool
|
||||
#define FIXX11H_Bool
|
||||
#ifdef _XTYPEDEF_BOOL /* Xdefs.h has typedef'ed Bool already */
|
||||
#undef Bool
|
||||
#else
|
||||
typedef Bool XBool;
|
||||
#undef Bool
|
||||
typedef XBool Bool;
|
||||
#endif
|
||||
#endif
|
||||
#undef Bool
|
||||
#define _XTYPEDEF_BOOL
|
||||
#endif
|
||||
// template <---
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef KeyPress
|
||||
#ifndef FIXX11H_KeyPress
|
||||
#define FIXX11H_KeyPress
|
||||
const int XKeyPress = KeyPress;
|
||||
#undef KeyPress
|
||||
const int KeyPress = XKeyPress;
|
||||
#endif
|
||||
#undef KeyPress
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef KeyRelease
|
||||
#ifndef FIXX11H_KeyRelease
|
||||
#define FIXX11H_KeyRelease
|
||||
const int XKeyRelease = KeyRelease;
|
||||
#undef KeyRelease
|
||||
const int KeyRelease = XKeyRelease;
|
||||
#endif
|
||||
#undef KeyRelease
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Above
|
||||
#ifndef FIXX11H_Above
|
||||
#define FIXX11H_Above
|
||||
const int XAbove = Above;
|
||||
#undef Above
|
||||
const int Above = XAbove;
|
||||
#endif
|
||||
#undef Above
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Below
|
||||
#ifndef FIXX11H_Below
|
||||
#define FIXX11H_Below
|
||||
const int XBelow = Below;
|
||||
#undef Below
|
||||
const int Below = XBelow;
|
||||
#endif
|
||||
#undef Below
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef FocusIn
|
||||
#ifndef FIXX11H_FocusIn
|
||||
#define FIXX11H_FocusIn
|
||||
const int XFocusIn = FocusIn;
|
||||
#undef FocusIn
|
||||
const int FocusIn = XFocusIn;
|
||||
#endif
|
||||
#undef FocusIn
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef FocusOut
|
||||
#ifndef FIXX11H_FocusOut
|
||||
#define FIXX11H_FocusOut
|
||||
const int XFocusOut = FocusOut;
|
||||
#undef FocusOut
|
||||
const int FocusOut = XFocusOut;
|
||||
#endif
|
||||
#undef FocusOut
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Always
|
||||
#ifndef FIXX11H_Always
|
||||
#define FIXX11H_Always
|
||||
const int XAlways = Always;
|
||||
#undef Always
|
||||
const int Always = XAlways;
|
||||
#endif
|
||||
#undef Always
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Expose
|
||||
#ifndef FIXX11H_Expose
|
||||
#define FIXX11H_Expose
|
||||
const int XExpose = Expose;
|
||||
#undef Expose
|
||||
const int Expose = XExpose;
|
||||
#endif
|
||||
#undef Expose
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Success
|
||||
#ifndef FIXX11H_Success
|
||||
#define FIXX11H_Success
|
||||
const int XSuccess = Success;
|
||||
#undef Success
|
||||
const int Success = XSuccess;
|
||||
#endif
|
||||
#undef Success
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef GrayScale
|
||||
#ifndef FIXX11H_GrayScale
|
||||
#define FIXX11H_GrayScale
|
||||
const int XGrayScale = GrayScale;
|
||||
#undef GrayScale
|
||||
const int GrayScale = XGrayScale;
|
||||
#endif
|
||||
#undef GrayScale
|
||||
#endif
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef Status
|
||||
#ifndef FIXX11H_Status
|
||||
#define FIXX11H_Status
|
||||
typedef Status XStatus;
|
||||
#undef Status
|
||||
typedef XStatus Status;
|
||||
#endif
|
||||
#undef Status
|
||||
#endif
|
||||
|
||||
// template --->
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef CursorShape
|
||||
#ifndef FIXX11H_CursorShape
|
||||
#define FIXX11H_CursorShape
|
||||
const int XCursorShape = CursorShape;
|
||||
#undef CursorShape
|
||||
const int CursorShape = XCursorShape;
|
||||
#endif
|
||||
#undef CursorShape
|
||||
#endif
|
||||
// template <---
|
||||
|
||||
// template --->
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef FontChange
|
||||
#ifndef FIXX11H_FontChange
|
||||
#define FIXX11H_FontChange
|
||||
const int XFontChange = FontChange;
|
||||
#undef FontChange
|
||||
const int FontChange = XFontChange;
|
||||
#endif
|
||||
#undef FontChange
|
||||
#endif
|
||||
// template <---
|
||||
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef NormalState
|
||||
#ifndef FIXX11H_NormalState
|
||||
#define FIXX11H_NormalState
|
||||
const int XNormalState = NormalState;
|
||||
#undef NormalState
|
||||
const int NormalState = XNormalState;
|
||||
#endif
|
||||
#undef NormalState
|
||||
#endif
|
||||
|
||||
// template --->
|
||||
// Affects: Should be without side effects.
|
||||
#ifdef index
|
||||
#ifndef FIXX11H_index
|
||||
#define FIXX11H_index
|
||||
inline const char *Xindex(const char *s, int c)
|
||||
{
|
||||
return index(s, c);
|
||||
}
|
||||
#undef index
|
||||
inline const char *index(const char *s, int c)
|
||||
{
|
||||
return Xindex(s, c);
|
||||
}
|
||||
#endif
|
||||
#undef index
|
||||
#endif
|
||||
// template <---
|
||||
|
||||
#ifdef rindex
|
||||
// Affects: Should be without side effects.
|
||||
#ifndef FIXX11H_rindex
|
||||
#define FIXX11H_rindex
|
||||
inline const char *Xrindex(const char *s, int c)
|
||||
{
|
||||
return rindex(s, c);
|
||||
}
|
||||
#undef rindex
|
||||
inline const char *rindex(const char *s, int c)
|
||||
{
|
||||
return Xrindex(s, c);
|
||||
}
|
||||
#endif
|
||||
#undef rindex
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace X;
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"platforms": ["xcb"]
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
/* This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
// Exceptionnally, include QCoreApplication before our own header, because that one includes X11 headers (#define None...)
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "xsync_logging.h"
|
||||
|
||||
#include "xsyncbasedpoller.h"
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <X11/Xlib-xcb.h> // XGetXCBConnection
|
||||
#include <xcb/sync.h>
|
||||
|
||||
class XSyncBasedPollerHelper : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
XSyncBasedPollerHelper()
|
||||
: q(nullptr)
|
||||
, isActive(false)
|
||||
{
|
||||
}
|
||||
~XSyncBasedPollerHelper() override
|
||||
{
|
||||
delete q;
|
||||
}
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
if (isActive && eventType == "xcb_generic_event_t") {
|
||||
q->xcbEvent(reinterpret_cast<xcb_generic_event_t *>(message));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
XSyncBasedPoller *q;
|
||||
bool isActive;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(XSyncBasedPollerHelper, s_globalXSyncBasedPoller)
|
||||
|
||||
XSyncBasedPoller *XSyncBasedPoller::instance()
|
||||
{
|
||||
if (!s_globalXSyncBasedPoller()->q) {
|
||||
new XSyncBasedPoller;
|
||||
}
|
||||
|
||||
return s_globalXSyncBasedPoller()->q;
|
||||
}
|
||||
|
||||
XSyncBasedPoller::XSyncBasedPoller(QObject *parent)
|
||||
: KAbstractIdleTimePoller(parent)
|
||||
, m_display(qGuiApp->nativeInterface<QNativeInterface::QX11Application>()->display())
|
||||
, m_xcb_connection(nullptr)
|
||||
, m_sync_event(0)
|
||||
, m_idleCounter(None)
|
||||
, m_resetAlarm(None)
|
||||
, m_available(true)
|
||||
{
|
||||
Q_ASSERT(!s_globalXSyncBasedPoller()->q);
|
||||
s_globalXSyncBasedPoller()->q = this;
|
||||
|
||||
if (Q_UNLIKELY(!m_display)) {
|
||||
m_available = false;
|
||||
qCWarning(KIDLETIME_XSYNC_PLUGIN) << "xcb sync could not find display";
|
||||
return;
|
||||
}
|
||||
m_xcb_connection = XGetXCBConnection(m_display);
|
||||
|
||||
QCoreApplication::instance()->installNativeEventFilter(s_globalXSyncBasedPoller());
|
||||
|
||||
const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(m_xcb_connection, &xcb_sync_id);
|
||||
if (!sync_reply || !sync_reply->present) {
|
||||
qCWarning(KIDLETIME_XSYNC_PLUGIN) << "xcb sync extension not found";
|
||||
m_available = false;
|
||||
return;
|
||||
}
|
||||
m_sync_event = sync_reply->first_event;
|
||||
|
||||
#if 0
|
||||
|
||||
// Workaround for https://bugs.freedesktop.org/show_bug.cgi?id=23403
|
||||
#define xcb_sync_systemcounter_name(sc) (((char *)&(sc)->name_len) + 2)
|
||||
|
||||
xcb_sync_list_system_counters_cookie_t cookie = xcb_sync_list_system_counters(m_xcb_connection);
|
||||
xcb_sync_list_system_counters_reply_t *reply = xcb_sync_list_system_counters_reply(m_xcb_connection, cookie, NULL);
|
||||
|
||||
xcb_sync_systemcounter_iterator_t iter;
|
||||
for (iter = xcb_sync_list_system_counters_counters_iterator(reply);
|
||||
iter.rem; xcb_sync_systemcounter_next(&iter)) {
|
||||
printf("%d: %.*s\n", iter.data->counter,
|
||||
iter.data->name_len, xcb_sync_systemcounter_name(iter.data));
|
||||
/* Extra info for debugging: */
|
||||
printf(" Actual name: %.*s\n", iter.data->name_len,
|
||||
((char *) &iter.data->name_len) + 2);
|
||||
}
|
||||
|
||||
int xcbcounters = xcb_sync_list_system_counters_counters_length(reply);
|
||||
xcb_sync_systemcounter_iterator_t it = xcb_sync_list_system_counters_counters_iterator(reply);
|
||||
for (int i = 0; i < xcbcounters; ++i) {
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << it.data->counter << it.rem << it.index;
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "name length" << xcb_sync_systemcounter_name_length(it.data);
|
||||
QByteArray name(xcb_sync_systemcounter_name(it.data), xcb_sync_systemcounter_name_length(it.data));
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << name;
|
||||
xcb_sync_systemcounter_next(&it);
|
||||
}
|
||||
delete reply;
|
||||
#endif
|
||||
|
||||
int sync_major;
|
||||
int sync_minor;
|
||||
int old_sync_event;
|
||||
int old_sync_error;
|
||||
if (!XSyncQueryExtension(m_display, &old_sync_event, &old_sync_error)) {
|
||||
m_available = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!XSyncInitialize(m_display, &sync_major, &sync_minor)) {
|
||||
m_available = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int ncounters;
|
||||
XSyncSystemCounter *counters = XSyncListSystemCounters(m_display, &ncounters);
|
||||
|
||||
bool idleFound = false;
|
||||
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << ncounters << "counters";
|
||||
for (int i = 0; i < ncounters; ++i) {
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << counters[i].name << counters[i].counter;
|
||||
if (!strcmp(counters[i].name, "IDLETIME")) {
|
||||
m_idleCounter = counters[i].counter;
|
||||
idleFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XSyncFreeSystemCounterList(counters);
|
||||
|
||||
if (!idleFound) {
|
||||
m_available = false;
|
||||
}
|
||||
|
||||
if (m_available) {
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "XSync seems available and ready";
|
||||
} else {
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "XSync seems not available";
|
||||
}
|
||||
}
|
||||
|
||||
XSyncBasedPoller::~XSyncBasedPoller()
|
||||
{
|
||||
}
|
||||
|
||||
bool XSyncBasedPoller::isAvailable()
|
||||
{
|
||||
return m_available;
|
||||
}
|
||||
|
||||
bool XSyncBasedPoller::setUpPoller()
|
||||
{
|
||||
if (!isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "XSync Inited";
|
||||
|
||||
s_globalXSyncBasedPoller()->isActive = true;
|
||||
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "Supported, init completed";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::unloadPoller()
|
||||
{
|
||||
s_globalXSyncBasedPoller()->isActive = false;
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::addTimeout(int nextTimeout)
|
||||
{
|
||||
/* We need to set the counter to the idle time + the value
|
||||
* requested for next timeout
|
||||
*/
|
||||
|
||||
// If there's already an alarm for the requested timeout, skip
|
||||
if (m_timeoutAlarm.contains(nextTimeout)) {
|
||||
return;
|
||||
}
|
||||
|
||||
XSyncValue timeout;
|
||||
XSyncAlarm newalarm = None;
|
||||
|
||||
XSyncIntToValue(&timeout, nextTimeout);
|
||||
|
||||
setAlarm(m_display, &newalarm, m_idleCounter, XSyncPositiveComparison, timeout);
|
||||
|
||||
m_timeoutAlarm.insert(nextTimeout, newalarm);
|
||||
}
|
||||
|
||||
int XSyncBasedPoller::forcePollRequest()
|
||||
{
|
||||
return poll();
|
||||
}
|
||||
|
||||
int XSyncBasedPoller::poll()
|
||||
{
|
||||
XSyncValue idleTime;
|
||||
XSyncQueryCounter(m_display, m_idleCounter, &idleTime);
|
||||
|
||||
return XSyncValueLow32(idleTime);
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::removeTimeout(int timeout)
|
||||
{
|
||||
if (m_timeoutAlarm.contains(timeout)) {
|
||||
XSyncAlarm a = m_timeoutAlarm[timeout];
|
||||
XSyncDestroyAlarm(m_display, a);
|
||||
m_timeoutAlarm.remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
QList<int> XSyncBasedPoller::timeouts() const
|
||||
{
|
||||
return m_timeoutAlarm.keys();
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::stopCatchingIdleEvents()
|
||||
{
|
||||
if (m_resetAlarm != None) {
|
||||
XSyncDestroyAlarm(m_display, m_resetAlarm);
|
||||
m_resetAlarm = None;
|
||||
}
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::catchIdleEvent()
|
||||
{
|
||||
XSyncValue idleTime;
|
||||
|
||||
XSyncQueryCounter(m_display, m_idleCounter, &idleTime);
|
||||
|
||||
/* Set the reset alarm to fire the next time idleCounter < the
|
||||
* current counter value. XSyncNegativeComparison means <= so
|
||||
* we have to subtract 1 from the counter value
|
||||
*/
|
||||
|
||||
// NOTE: this must be a int, else compilation might fail
|
||||
int overflow;
|
||||
XSyncValue add;
|
||||
XSyncValue plusone;
|
||||
XSyncIntToValue(&add, -1);
|
||||
XSyncValueAdd(&plusone, idleTime, add, &overflow);
|
||||
setAlarm(m_display, &m_resetAlarm, m_idleCounter, XSyncNegativeComparison, plusone);
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::reloadAlarms()
|
||||
{
|
||||
XSyncValue timeout;
|
||||
|
||||
for (QHash<int, XSyncAlarm>::iterator i = m_timeoutAlarm.begin(); i != m_timeoutAlarm.end(); ++i) {
|
||||
XSyncIntToValue(&timeout, i.key());
|
||||
|
||||
setAlarm(m_display, &(i.value()), m_idleCounter, XSyncPositiveComparison, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
bool XSyncBasedPoller::xcbEvent(xcb_generic_event_t *event)
|
||||
{
|
||||
// qCDebug(KIDLETIME_XSYNC_PLUGIN) << event->response_type << "waiting for" << m_sync_event+XCB_SYNC_ALARM_NOTIFY;
|
||||
if (event->response_type != m_sync_event + XCB_SYNC_ALARM_NOTIFY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
xcb_sync_alarm_notify_event_t *alarmEvent = reinterpret_cast<xcb_sync_alarm_notify_event_t *>(event);
|
||||
|
||||
if (alarmEvent->state == XCB_SYNC_ALARMSTATE_DESTROYED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (QHash<int, XSyncAlarm>::const_iterator i = m_timeoutAlarm.constBegin(); i != m_timeoutAlarm.constEnd(); ++i) {
|
||||
if (alarmEvent->alarm == i.value()) {
|
||||
/* Bling! Caught! */
|
||||
Q_EMIT timeoutReached(i.key());
|
||||
// Update the alarm to fire back if the system gets inactive for the same time
|
||||
catchIdleEvent();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (alarmEvent->alarm == m_resetAlarm) {
|
||||
/* Resuming from idle here! */
|
||||
stopCatchingIdleEvents();
|
||||
reloadAlarms();
|
||||
Q_EMIT resumingFromIdle();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter counter, XSyncTestType test, XSyncValue value)
|
||||
{
|
||||
XSyncAlarmAttributes attr;
|
||||
XSyncValue delta;
|
||||
unsigned int flags;
|
||||
|
||||
XSyncIntToValue(&delta, 0);
|
||||
|
||||
attr.trigger.counter = counter;
|
||||
attr.trigger.value_type = XSyncAbsolute;
|
||||
attr.trigger.test_type = test;
|
||||
attr.trigger.wait_value = value;
|
||||
attr.delta = delta;
|
||||
|
||||
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | XSyncCAValue | XSyncCADelta;
|
||||
|
||||
if (*alarm) {
|
||||
// xcb_sync_change_alarm_checked(m_xcb_connection, alarmId, ...
|
||||
XSyncChangeAlarm(dpy, *alarm, flags, &attr);
|
||||
} else {
|
||||
*alarm = XSyncCreateAlarm(dpy, flags, &attr);
|
||||
qCDebug(KIDLETIME_XSYNC_PLUGIN) << "Created alarm" << *alarm;
|
||||
}
|
||||
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
void XSyncBasedPoller::simulateUserActivity()
|
||||
{
|
||||
XResetScreenSaver(m_display);
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
#include "moc_xsyncbasedpoller.cpp"
|
||||
@@ -0,0 +1,68 @@
|
||||
/* This file is part of the KDE libraries
|
||||
* SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef XSYNCBASEDPOLLER_H
|
||||
#define XSYNCBASEDPOLLER_H
|
||||
|
||||
#include "kabstractidletimepoller_p.h"
|
||||
#include <QHash>
|
||||
|
||||
#include <config-kidletime.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/sync.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "fixx11h.h"
|
||||
|
||||
class XSyncBasedPoller : public KAbstractIdleTimePoller
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID KAbstractIdleTimePoller_iid FILE "xcb.json")
|
||||
Q_INTERFACES(KAbstractIdleTimePoller)
|
||||
|
||||
public:
|
||||
static XSyncBasedPoller *instance();
|
||||
|
||||
explicit XSyncBasedPoller(QObject *parent = nullptr);
|
||||
~XSyncBasedPoller() override;
|
||||
|
||||
bool isAvailable() override;
|
||||
bool setUpPoller() override;
|
||||
void unloadPoller() override;
|
||||
|
||||
bool xcbEvent(xcb_generic_event_t *event);
|
||||
|
||||
QList<int> timeouts() const override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void addTimeout(int nextTimeout) override;
|
||||
void removeTimeout(int nextTimeout) override;
|
||||
|
||||
int forcePollRequest() override;
|
||||
void catchIdleEvent() override;
|
||||
void stopCatchingIdleEvents() override;
|
||||
void simulateUserActivity() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
int poll();
|
||||
void reloadAlarms();
|
||||
|
||||
private:
|
||||
void setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter counter, XSyncTestType test, XSyncValue value);
|
||||
|
||||
private:
|
||||
Display *m_display;
|
||||
xcb_connection_t *m_xcb_connection;
|
||||
|
||||
int m_sync_event;
|
||||
XSyncCounter m_idleCounter;
|
||||
QHash<int, XSyncAlarm> m_timeoutAlarm;
|
||||
XSyncAlarm m_resetAlarm;
|
||||
bool m_available;
|
||||
};
|
||||
|
||||
#endif /* XSYNCBASEDPOLLER_H */
|
||||
Reference in New Issue
Block a user