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 
19 Q_DECLARE_LOGGING_CATEGORY(POLLER)
20 Q_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 
32 class IdleTimeout : public QObject
33 {
34  Q_OBJECT
35 public:
36  IdleTimeout() = default;
37 Q_SIGNALS:
38  void idle();
39  void resumeFromIdle();
40 };
41 
42 class IdleTimeoutKwin : public IdleTimeout, public QtWayland::org_kde_kwin_idle_timeout
43 {
44  Q_OBJECT
45 public:
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 
58 protected:
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 
67 class IdleTimeoutExt : public IdleTimeout, public QtWayland::ext_idle_notification_v1
68 {
69  Q_OBJECT
70 public:
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 
84 protected:
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 
95 class IdleManagerKwin : public QWaylandClientExtensionTemplate<IdleManagerKwin>, public QtWayland::org_kde_kwin_idle
96 {
97 public:
98  IdleManagerKwin()
99  : QWaylandClientExtensionTemplate<IdleManagerKwin>(1)
100  {
101  initialize();
102  }
103 };
104 
105 class IdleManagerExt : public QWaylandClientExtensionTemplate<IdleManagerExt>, public QtWayland::ext_idle_notifier_v1
106 {
107 public:
108  IdleManagerExt()
109  : QWaylandClientExtensionTemplate<IdleManagerExt>(1)
110  {
111  initialize();
112  }
113  ~IdleManagerExt()
114  {
115  if (qGuiApp && isActive()) {
116  destroy();
117  }
118  }
119 };
120 
121 Poller::Poller(QObject *parent)
122  : KAbstractIdleTimePoller(parent)
123  , m_idleManagerKwin(new IdleManagerKwin)
124  , m_idleManagerExt(new IdleManagerExt)
125 {
126 }
127 
128 Poller::~Poller() = default;
129 
130 bool Poller::isAvailable()
131 {
132  return m_idleManagerKwin->isActive() || m_idleManagerExt->isActive();
133 }
134 
135 void 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 
153 void Poller::removeTimeout(int nextTimeout)
154 {
155  m_timeouts.remove(nextTimeout);
156 }
157 
158 QList<int> Poller::timeouts() const
159 {
160  return QList<int>();
161 }
162 
163 void 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 
183 void Poller::stopCatchingIdleEvents()
184 {
185  m_catchResumeTimeout.reset();
186 }
187 
188 int Poller::forcePollRequest()
189 {
190  qCWarning(POLLER) << "This plugin does not support polling idle time";
191  return 0;
192 }
193 
194 void Poller::simulateUserActivity()
195 {
196 }
197 
198 IdleTimeout* 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"
Q_OBJECTQ_OBJECT
Q_EMITQ_EMIT
void initialize(StandardShortcut id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Thu Feb 15 2024 04:07:39 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.