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

KDE's Doxygen guidelines are available online.