KIdleTime

poller.cpp
1/*
2 SPDX-FileCopyrightText: 2021 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#include "poller.h"
7
8#include <QDebug>
9#include <QGuiApplication>
10#include <QLoggingCategory>
11#include <QWaylandClientExtensionTemplate>
12#include <QtWaylandClientVersion>
13
14#include <qpa/qplatformnativeinterface.h>
15
16#include "qwayland-ext-idle-notify-v1.h"
17#include "qwayland-idle.h"
18
19Q_DECLARE_LOGGING_CATEGORY(POLLER)
20Q_LOGGING_CATEGORY(POLLER, "kf5idletime_wayland")
21
22/*
23 * Porting notes:
24 * org_kde_kwin_idle refers to an early specific idle timeout protocol
25 * the version ext_idle refers to an upstream stable protocol
26 *
27 * Pragmattically they're both the same, but we have to have two implementations for a while
28 *
29 * 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
30 */
31
32class IdleTimeout : public QObject
33{
34 Q_OBJECT
35public:
36 IdleTimeout() = default;
37Q_SIGNALS:
38 void idle();
39 void resumeFromIdle();
40};
41
42class IdleTimeoutKwin : public IdleTimeout, public QtWayland::org_kde_kwin_idle_timeout
43{
45public:
46 IdleTimeoutKwin(struct ::org_kde_kwin_idle_timeout *object)
47 : IdleTimeout()
48 , QtWayland::org_kde_kwin_idle_timeout(object)
49 {}
50
51 ~IdleTimeoutKwin()
52 {
53 if (qGuiApp) {
54 release();
55 }
56 }
57
58protected:
59 void org_kde_kwin_idle_timeout_idle() override {
60 Q_EMIT idle();
61 }
62 void org_kde_kwin_idle_timeout_resumed() override {
63 Q_EMIT resumeFromIdle();
64 }
65};
66
67class IdleTimeoutExt : public IdleTimeout, public QtWayland::ext_idle_notification_v1
68{
70public:
71 IdleTimeoutExt(struct ::ext_idle_notification_v1 *object)
72 : IdleTimeout()
73 , QtWayland::ext_idle_notification_v1(object)
74 {
75 }
76
77 ~IdleTimeoutExt()
78 {
79 if (qGuiApp) {
80 destroy();
81 }
82 }
83
84protected:
85 void ext_idle_notification_v1_idled() override
86 {
87 Q_EMIT idle();
88 }
89 void ext_idle_notification_v1_resumed() override
90 {
91 Q_EMIT resumeFromIdle();
92 }
93};
94
95class IdleManagerKwin : public QWaylandClientExtensionTemplate<IdleManagerKwin>, public QtWayland::org_kde_kwin_idle
96{
97public:
98 IdleManagerKwin()
99 : QWaylandClientExtensionTemplate<IdleManagerKwin>(1)
100 {
101 initialize();
102 }
103};
104
105class IdleManagerExt : public QWaylandClientExtensionTemplate<IdleManagerExt>, public QtWayland::ext_idle_notifier_v1
106{
107public:
108 IdleManagerExt()
109 : QWaylandClientExtensionTemplate<IdleManagerExt>(1)
110 {
111 initialize();
112 }
113 ~IdleManagerExt()
114 {
115 if (qGuiApp && isActive()) {
116 destroy();
117 }
118 }
119};
120
121Poller::Poller(QObject *parent)
122 : KAbstractIdleTimePoller(parent)
123 , m_idleManagerKwin(new IdleManagerKwin)
124 , m_idleManagerExt(new IdleManagerExt)
125{
126}
127
128Poller::~Poller() = default;
129
130bool Poller::isAvailable()
131{
132 return m_idleManagerKwin->isActive() || m_idleManagerExt->isActive();
133}
134
135void Poller::addTimeout(int nextTimeout)
136{
137 if (m_timeouts.contains(nextTimeout)) {
138 return;
139 }
140
141 auto timeout = createTimeout(nextTimeout);
142 if (!timeout) {
143 return;
144 }
145
146 connect(timeout, &IdleTimeout::idle, this, [this, nextTimeout] {
147 Q_EMIT timeoutReached(nextTimeout);
148 });
149 connect(timeout, &IdleTimeout::resumeFromIdle, this, &Poller::resumingFromIdle);
150 m_timeouts.insert(nextTimeout, QSharedPointer<IdleTimeout>(timeout));
151}
152
153void Poller::removeTimeout(int nextTimeout)
154{
155 m_timeouts.remove(nextTimeout);
156}
157
158QList<int> Poller::timeouts() const
159{
160 return QList<int>();
161}
162
163void Poller::catchIdleEvent()
164{
165 if (m_catchResumeTimeout) {
166 // already setup
167 return;
168 }
169 if (!isAvailable()) {
170 return;
171 }
172
173 m_catchResumeTimeout.reset(createTimeout(0));
174 if (!m_catchResumeTimeout) {
175 return;
176 }
177 connect(m_catchResumeTimeout.get(), &IdleTimeout::resumeFromIdle, this, [this] {
178 stopCatchingIdleEvents();
179 Q_EMIT resumingFromIdle();
180 });
181}
182
183void Poller::stopCatchingIdleEvents()
184{
185 m_catchResumeTimeout.reset();
186}
187
188int Poller::forcePollRequest()
189{
190 qCWarning(POLLER) << "This plugin does not support polling idle time";
191 return 0;
192}
193
194void Poller::simulateUserActivity()
195{
196}
197
198IdleTimeout* Poller::createTimeout(int timeout)
199{
200 QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
201 if (!nativeInterface) {
202 return nullptr;
203 }
204 auto seat = static_cast<wl_seat *>(nativeInterface->nativeResourceForIntegration("wl_seat"));
205 if (!seat) {
206 return nullptr;
207 }
208
209 if (m_idleManagerExt->isActive()) {
210 return new IdleTimeoutExt(m_idleManagerExt->get_idle_notification(timeout, seat));
211 }
212 if (m_idleManagerKwin->isActive()) {
213 return new IdleTimeoutKwin(m_idleManagerKwin->get_idle_timeout(seat, timeout));
214 }
215 return nullptr;
216}
217
218#include "moc_poller.cpp"
219#include "poller.moc"
void initialize(StandardShortcut id)
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
bool remove(const Key &key)
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
T * get() const const
void reset(T *other)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:49:20 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.