mirror of
https://github.com/ckb-next/ckb-next.git
synced 2026-10-10 12:27:21 -04:00
Add Wayland idle timer
Wayland idle timer use ext_idle_notifier_v1 Wayland protocol to be notified of user idle status. It will only run if the compositor implement the protocol. For ext_idle_notifier_v1 version 2, get_input_idle_notification() only tracks user input, which I think is more appropriate. Due to the usage of qt_generate_wayland_protocol_client_sources() in CMake to generate Wayland client code, Wayland idle timer can only be compiled using Qt 6. We could take relevant part from KDE's ECM FindQtWaylandScanner, but that seem cumbersome.
This commit is contained in:
+1
-1
@@ -107,7 +107,7 @@ if (LINUX)
|
||||
cmake_dependent_option(WITH_MVIZ "Build with music visualizer." ON "WITH_ANIMATIONS;WITH_GUI" OFF)
|
||||
cmake_dependent_option(USE_XCB "Build with features that require XCB." ON "WITH_GUI" OFF)
|
||||
cmake_dependent_option(USE_DBUS_MENU "Build with DBus support for the tray." ON "WITH_GUI" OFF)
|
||||
cmake_dependent_option(USE_WAYLAND "Build with features that require Wayland." ON "WITH_GUI" OFF)
|
||||
cmake_dependent_option(USE_WAYLAND "Build with features that require Wayland." ON "WITH_GUI;PREFER_QT6" OFF)
|
||||
option(USE_PORTAUDIO "Use portaudio for music visualizer." OFF)
|
||||
else ()
|
||||
cmake_dependent_option(WITH_MVIZ "Build with music visualizer." OFF "WITH_ANIMATIONS;WITH_GUI" OFF)
|
||||
|
||||
@@ -414,6 +414,40 @@ elseif (LINUX)
|
||||
|
||||
if (USE_WAYLAND)
|
||||
find_package(Wayland COMPONENTS Client REQUIRED)
|
||||
find_package(WaylandProtocols REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS WaylandClient)
|
||||
|
||||
if (QT_VERSION VERSION_GREATER_EQUAL "6.0.0")
|
||||
if (NOT EXISTS ${WaylandProtocols_DATADIR}/staging/ext-idle-notify/ext-idle-notify-v1.xml)
|
||||
message(FATAL_ERROR "Wayland ext-idle-notify-v1 protocol is not found. Either install them or pass -DUSE_WAYLAND=0 to disable idle detection.")
|
||||
endif ()
|
||||
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL "6.8.0")
|
||||
set(private_code_option "PRIVATE_CODE")
|
||||
endif()
|
||||
|
||||
qt_generate_wayland_protocol_client_sources(
|
||||
ckb-next
|
||||
${private_code_option}
|
||||
FILES
|
||||
${WaylandProtocols_DATADIR}/staging/ext-idle-notify/ext-idle-notify-v1.xml
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ckb-next
|
||||
PRIVATE
|
||||
wayland/waylandidletimer.cpp
|
||||
wayland/waylandidletimer.h
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
ckb-next
|
||||
PRIVATE
|
||||
USE_WAYLAND_IDLE_NOTIFY
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "Wayland idle detection required Qt 6 or later. Either build with Qt 6 or pass -DUSE_WAYLAND=0 to disable idle detection.")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(
|
||||
ckb-next
|
||||
@@ -425,6 +459,7 @@ elseif (LINUX)
|
||||
ckb-next
|
||||
PRIVATE
|
||||
Wayland::Client
|
||||
Qt${QT_VERSION_MAJOR}::WaylandClient
|
||||
)
|
||||
|
||||
if (Qt6_VERSION VERSION_LESS "6.5.0")
|
||||
|
||||
+10
-2
@@ -11,12 +11,20 @@
|
||||
#include "xcb/xcbidletimer.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_WAYLAND_IDLE_NOTIFY
|
||||
#include "wayland/waylandidletimer.h"
|
||||
#endif
|
||||
|
||||
class IdleTimerHelper {
|
||||
public:
|
||||
QScopedPointer<IdleTimerImpl> m_impl;
|
||||
|
||||
IdleTimerHelper() {
|
||||
if (!WaylandUtils::isWayland()) {
|
||||
if (WaylandUtils::isWayland()) {
|
||||
#ifdef USE_WAYLAND_IDLE_NOTIFY
|
||||
m_impl.reset(new WaylandIdleTimer());
|
||||
#endif
|
||||
} else {
|
||||
#ifdef USE_XCB_SCREENSAVER
|
||||
m_impl.reset(new XcbIdleTimer());
|
||||
#endif
|
||||
@@ -37,5 +45,5 @@ int IdleTimer::getIdleTime()
|
||||
|
||||
bool IdleTimer::isSupported()
|
||||
{
|
||||
return g_helper->m_impl.isNull();
|
||||
return g_helper->m_impl.isNull() ? false : g_helper->m_impl->isSupported();
|
||||
}
|
||||
|
||||
+4
-1
@@ -3,7 +3,10 @@
|
||||
|
||||
class IdleTimerImpl {
|
||||
public:
|
||||
virtual int getIdleTime() = 0;
|
||||
virtual int getIdleTime() const = 0;
|
||||
virtual inline bool isSupported() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class IdleTimer
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "waylandidletimer.h"
|
||||
|
||||
#ifdef USE_WAYLAND_IDLE_NOTIFY
|
||||
#include "wayland/waylandutils.h"
|
||||
#include "qwayland-ext-idle-notify-v1.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QDateTime>
|
||||
#include <QWaylandClientExtensionTemplate>
|
||||
|
||||
class WaylandIdleNotification : public QtWayland::ext_idle_notification_v1 {
|
||||
public:
|
||||
WaylandIdleNotification(struct ::ext_idle_notification_v1 *object)
|
||||
: QtWayland::ext_idle_notification_v1(object)
|
||||
{}
|
||||
|
||||
~WaylandIdleNotification()
|
||||
{
|
||||
if (qGuiApp) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
qint64 m_idleAt = -1;
|
||||
|
||||
protected:
|
||||
void ext_idle_notification_v1_idled() override
|
||||
{
|
||||
m_idleAt = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
void ext_idle_notification_v1_resumed() override
|
||||
{
|
||||
m_idleAt = -1;
|
||||
}
|
||||
};
|
||||
|
||||
class WaylandIdleNotifier : public QWaylandClientExtensionTemplate<WaylandIdleNotifier>, public QtWayland::ext_idle_notifier_v1 {
|
||||
public:
|
||||
WaylandIdleNotifier()
|
||||
: QWaylandClientExtensionTemplate<WaylandIdleNotifier>(2)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
~WaylandIdleNotifier()
|
||||
{
|
||||
if (qGuiApp && isActive()) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
WaylandIdleTimer::WaylandIdleTimer()
|
||||
: m_supported{WaylandUtils::hasInterface("ext_idle_notifier_v1", 1)}
|
||||
{
|
||||
if (m_supported) {
|
||||
auto seat = WaylandUtils::seat();
|
||||
m_notifier.reset(new WaylandIdleNotifier());
|
||||
if (WaylandUtils::hasInterface("ext_idle_notifier_v1", 2)) {
|
||||
m_notification.reset(new WaylandIdleNotification(m_notifier->get_input_idle_notification(0, seat)));
|
||||
} else {
|
||||
m_notification.reset(new WaylandIdleNotification(m_notifier->get_idle_notification(0, seat)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WaylandIdleTimer::getIdleTime() const
|
||||
{
|
||||
if (m_supported) {
|
||||
const auto idleAt = m_notification->m_idleAt;
|
||||
if (idleAt >= 0) {
|
||||
const auto idleTime = QDateTime::currentMSecsSinceEpoch() - idleAt;
|
||||
if (idleTime > INT_MAX) {
|
||||
return INT_MAX;
|
||||
}
|
||||
return (int)idleTime;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WaylandIdleTimer::isSupported() const
|
||||
{
|
||||
return m_supported;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef WAYLANDIDLETIMER_HPP
|
||||
#define WAYLANDIDLETIMER_HPP
|
||||
|
||||
#ifdef USE_WAYLAND_IDLE_NOTIFY
|
||||
#include "idletimer.h"
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
class WaylandIdleNotifier;
|
||||
class WaylandIdleNotification;
|
||||
class WaylandIdleTimer : public IdleTimerImpl
|
||||
{
|
||||
public:
|
||||
WaylandIdleTimer();
|
||||
|
||||
int getIdleTime() const override;
|
||||
bool isSupported() const override;
|
||||
|
||||
private:
|
||||
bool m_supported;
|
||||
QScopedPointer<WaylandIdleNotifier> m_notifier;
|
||||
QScopedPointer<WaylandIdleNotification> m_notification;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // WAYLANDIDLETIMER_HPP
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int XcbIdleTimer::getIdleTime()
|
||||
int XcbIdleTimer::getIdleTime() const
|
||||
{
|
||||
const MainWindow* const mw = MainWindow::mainWindow;
|
||||
if(!mw || !mw->windowHandle())
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
class XcbIdleTimer : public IdleTimerImpl
|
||||
{
|
||||
public:
|
||||
int getIdleTime() override;
|
||||
int getIdleTime() const override;
|
||||
};
|
||||
|
||||
#endif // XCBIDLETIMER_HPP
|
||||
|
||||
Reference in New Issue
Block a user