File indexing completed on 2024-11-10 04:57:03

0001 /*
0002     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "clockskewnotifierengine_linux.h"
0008 
0009 #include <QSocketNotifier>
0010 
0011 #include <cerrno>
0012 #include <fcntl.h>
0013 #include <sys/timerfd.h>
0014 #include <unistd.h>
0015 
0016 #ifndef TFD_TIMER_CANCEL_ON_SET // only available in newer glib
0017 #define TFD_TIMER_CANCEL_ON_SET (1 << 1)
0018 #endif
0019 
0020 namespace KWin
0021 {
0022 
0023 LinuxClockSkewNotifierEngine *LinuxClockSkewNotifierEngine::create(QObject *parent)
0024 {
0025     FileDescriptor fd{timerfd_create(CLOCK_REALTIME, O_CLOEXEC | O_NONBLOCK)};
0026     if (!fd.isValid()) {
0027         qWarning("Couldn't create clock skew notifier engine: %s", strerror(errno));
0028         return nullptr;
0029     }
0030 
0031     const itimerspec spec = {};
0032     const int ret = timerfd_settime(fd.get(), TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, nullptr);
0033     if (ret == -1) {
0034         qWarning("Couldn't create clock skew notifier engine: %s", strerror(errno));
0035         return nullptr;
0036     }
0037     return new LinuxClockSkewNotifierEngine(std::move(fd), parent);
0038 }
0039 
0040 LinuxClockSkewNotifierEngine::LinuxClockSkewNotifierEngine(FileDescriptor &&fd, QObject *parent)
0041     : ClockSkewNotifierEngine(parent)
0042     , m_fd(std::move(fd))
0043 {
0044     const QSocketNotifier *notifier = new QSocketNotifier(m_fd.get(), QSocketNotifier::Read, this);
0045     connect(notifier, &QSocketNotifier::activated, this, &LinuxClockSkewNotifierEngine::handleTimerCancelled);
0046 }
0047 
0048 void LinuxClockSkewNotifierEngine::handleTimerCancelled()
0049 {
0050     uint64_t expirationCount;
0051     read(m_fd.get(), &expirationCount, sizeof(expirationCount));
0052 
0053     Q_EMIT clockSkewed();
0054 }
0055 
0056 } // namespace KWin
0057 
0058 #include "moc_clockskewnotifierengine_linux.cpp"