8#include <QCoreApplication>
10#include "xsync_logging.h"
12#include "xsyncbasedpoller.h"
14#include <QAbstractNativeEventFilter>
15#include <QGuiApplication>
17#include <X11/Xlib-xcb.h>
23 XSyncBasedPollerHelper()
28 ~XSyncBasedPollerHelper()
override
32 bool nativeEventFilter(
const QByteArray &eventType,
void *message, qintptr *result)
override
35 if (isActive && eventType ==
"xcb_generic_event_t") {
36 q->xcbEvent(
reinterpret_cast<xcb_generic_event_t *
>(message));
44Q_GLOBAL_STATIC(XSyncBasedPollerHelper, s_globalXSyncBasedPoller)
46XSyncBasedPoller *XSyncBasedPoller::instance()
48 if (!s_globalXSyncBasedPoller()->q) {
52 return s_globalXSyncBasedPoller()->q;
55XSyncBasedPoller::XSyncBasedPoller(
QObject *parent)
56 : KAbstractIdleTimePoller(parent)
57 , m_display(qGuiApp->nativeInterface<
QNativeInterface::QX11Application>()->display())
58 , m_xcb_connection(nullptr)
64 Q_ASSERT(!s_globalXSyncBasedPoller()->q);
65 s_globalXSyncBasedPoller()->q =
this;
67 if (Q_UNLIKELY(!m_display)) {
69 qCWarning(KIDLETIME_XSYNC_PLUGIN) <<
"xcb sync could not find display";
72 m_xcb_connection = XGetXCBConnection(m_display);
76 const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(m_xcb_connection, &xcb_sync_id);
77 if (!sync_reply || !sync_reply->present) {
78 qCWarning(KIDLETIME_XSYNC_PLUGIN) <<
"xcb sync extension not found";
82 m_sync_event = sync_reply->first_event;
87#define xcb_sync_systemcounter_name(sc) (((char *)&(sc)->name_len) + 2)
89 xcb_sync_list_system_counters_cookie_t cookie = xcb_sync_list_system_counters(m_xcb_connection);
90 xcb_sync_list_system_counters_reply_t *reply = xcb_sync_list_system_counters_reply(m_xcb_connection, cookie, NULL);
92 xcb_sync_systemcounter_iterator_t iter;
93 for (iter = xcb_sync_list_system_counters_counters_iterator(reply);
94 iter.rem; xcb_sync_systemcounter_next(&iter)) {
95 printf(
"%d: %.*s\n", iter.data->counter,
96 iter.data->name_len, xcb_sync_systemcounter_name(iter.data));
98 printf(
" Actual name: %.*s\n", iter.data->name_len,
99 ((
char *) &iter.data->name_len) + 2);
102 int xcbcounters = xcb_sync_list_system_counters_counters_length(reply);
103 xcb_sync_systemcounter_iterator_t it = xcb_sync_list_system_counters_counters_iterator(reply);
104 for (
int i = 0; i < xcbcounters; ++i) {
105 qCDebug(KIDLETIME_XSYNC_PLUGIN) << it.data->counter << it.rem << it.index;
106 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"name length" << xcb_sync_systemcounter_name_length(it.data);
107 QByteArray name(xcb_sync_systemcounter_name(it.data), xcb_sync_systemcounter_name_length(it.data));
108 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
name;
109 xcb_sync_systemcounter_next(&it);
118 if (!XSyncQueryExtension(m_display, &old_sync_event, &old_sync_error)) {
123 if (!XSyncInitialize(m_display, &sync_major, &sync_minor)) {
129 XSyncSystemCounter *counters = XSyncListSystemCounters(m_display, &ncounters);
131 bool idleFound =
false;
133 qCDebug(KIDLETIME_XSYNC_PLUGIN) << ncounters <<
"counters";
134 for (
int i = 0; i < ncounters; ++i) {
135 qCDebug(KIDLETIME_XSYNC_PLUGIN) << counters[i].name << counters[i].counter;
136 if (!strcmp(counters[i].name,
"IDLETIME")) {
137 m_idleCounter = counters[i].counter;
143 XSyncFreeSystemCounterList(counters);
150 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"XSync seems available and ready";
152 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"XSync seems not available";
156XSyncBasedPoller::~XSyncBasedPoller()
160bool XSyncBasedPoller::isAvailable()
165bool XSyncBasedPoller::setUpPoller()
167 if (!isAvailable()) {
171 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"XSync Inited";
173 s_globalXSyncBasedPoller()->isActive =
true;
175 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"Supported, init completed";
180void XSyncBasedPoller::unloadPoller()
182 s_globalXSyncBasedPoller()->isActive =
false;
185void XSyncBasedPoller::addTimeout(
int nextTimeout)
192 if (m_timeoutAlarm.
contains(nextTimeout)) {
197 XSyncAlarm newalarm =
None;
199 XSyncIntToValue(&timeout, nextTimeout);
201 setAlarm(m_display, &newalarm, m_idleCounter, XSyncPositiveComparison, timeout);
203 m_timeoutAlarm.
insert(nextTimeout, newalarm);
206int XSyncBasedPoller::forcePollRequest()
211int XSyncBasedPoller::poll()
214 XSyncQueryCounter(m_display, m_idleCounter, &idleTime);
216 return XSyncValueLow32(idleTime);
219void XSyncBasedPoller::removeTimeout(
int timeout)
221 if (m_timeoutAlarm.
contains(timeout)) {
222 XSyncAlarm a = m_timeoutAlarm[timeout];
223 XSyncDestroyAlarm(m_display, a);
224 m_timeoutAlarm.
remove(timeout);
230 return m_timeoutAlarm.
keys();
233void XSyncBasedPoller::stopCatchingIdleEvents()
235 if (m_resetAlarm != None) {
236 XSyncDestroyAlarm(m_display, m_resetAlarm);
241void XSyncBasedPoller::catchIdleEvent()
245 XSyncQueryCounter(m_display, m_idleCounter, &idleTime);
256 XSyncIntToValue(&add, -1);
257 XSyncValueAdd(&plusone, idleTime, add, &overflow);
258 setAlarm(m_display, &m_resetAlarm, m_idleCounter, XSyncNegativeComparison, plusone);
261void XSyncBasedPoller::reloadAlarms()
266 XSyncIntToValue(&timeout, i.key());
268 setAlarm(m_display, &(i.value()), m_idleCounter, XSyncPositiveComparison, timeout);
272bool XSyncBasedPoller::xcbEvent(xcb_generic_event_t *event)
275 if (
event->response_type != m_sync_event + XCB_SYNC_ALARM_NOTIFY) {
279 xcb_sync_alarm_notify_event_t *alarmEvent =
reinterpret_cast<xcb_sync_alarm_notify_event_t *
>(
event);
281 if (alarmEvent->state == XCB_SYNC_ALARMSTATE_DESTROYED) {
286 if (alarmEvent->alarm == i.value()) {
288 Q_EMIT timeoutReached(i.key());
295 if (alarmEvent->alarm == m_resetAlarm) {
297 stopCatchingIdleEvents();
299 Q_EMIT resumingFromIdle();
305void XSyncBasedPoller::setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter counter, XSyncTestType test, XSyncValue value)
307 XSyncAlarmAttributes attr;
311 XSyncIntToValue(&delta, 0);
313 attr.trigger.counter = counter;
314 attr.trigger.value_type = XSyncAbsolute;
315 attr.trigger.test_type =
test;
316 attr.trigger.wait_value = value;
319 flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | XSyncCAValue | XSyncCADelta;
323 XSyncChangeAlarm(dpy, *alarm, flags, &attr);
325 *alarm = XSyncCreateAlarm(dpy, flags, &attr);
326 qCDebug(KIDLETIME_XSYNC_PLUGIN) <<
"Created alarm" << *alarm;
332void XSyncBasedPoller::simulateUserActivity()
334 XResetScreenSaver(m_display);
338#include "moc_xsyncbasedpoller.cpp"
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
QString name(StandardAction id)
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
QCoreApplication * instance()
const_iterator constBegin() const const
const_iterator constEnd() const const
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
QList< Key > keys() const const
bool remove(const Key &key)