2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-31 06:26:18 +00:00

Implement xcb-based LastUserInputTime method

This commit is contained in:
Ilya Fedin
2020-07-10 16:51:30 +04:00
committed by John Preston
parent c3f5de30be
commit 59b521d666
5 changed files with 110 additions and 42 deletions

View File

@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/linux/specific_linux.h"
#include "platform/linux/linux_libs.h"
#include "base/platform/base_platform_info.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "mainwindow.h"
@@ -23,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QStandardPaths>
#include <QtCore/QProcess>
#include <QtCore/QVersionNumber>
#include <qpa/qplatformnativeinterface.h>
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtDBus/QDBusInterface>
@@ -32,6 +34,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtDBus/QDBusError>
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <xcb/xcb.h>
#include <xcb/screensaver.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <cstdlib>
@@ -268,6 +273,83 @@ bool GenerateDesktopFile(
}
}
std::optional<crl::time> XCBLastUserInputTime() {
if (const auto native = QGuiApplication::platformNativeInterface()) {
const auto connection = reinterpret_cast<xcb_connection_t*>(
native->nativeResourceForIntegration(QByteArray("connection")));
if (!connection) {
return std::nullopt;
}
const auto screen = xcb_setup_roots_iterator(
xcb_get_setup(connection)).data;
if (!screen) {
return std::nullopt;
}
const auto cookie = xcb_screensaver_query_info(connection, screen->root);
auto info = xcb_screensaver_query_info_reply(connection, cookie, nullptr);
if (!info) {
return std::nullopt;
}
const auto idle = info->ms_since_user_input;
free(info);
return (crl::now() - static_cast<crl::time>(idle));
}
return std::nullopt;
}
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
std::optional<crl::time> DBusLastUserInputTime() {
static auto NotSupported = false;
if (NotSupported) {
return std::nullopt;
}
static const auto Message = QDBusMessage::createMethodCall(
qsl("org.freedesktop.ScreenSaver"),
qsl("/org/freedesktop/ScreenSaver"),
qsl("org.freedesktop.ScreenSaver"),
qsl("GetSessionIdleTime"));
const QDBusReply<uint> reply = QDBusConnection::sessionBus().call(
Message);
static const auto NotSupportedErrors = {
QDBusError::ServiceUnknown,
QDBusError::NotSupported,
};
static const auto NotSupportedErrorsToLog = {
QDBusError::Disconnected,
QDBusError::AccessDenied,
};
if (reply.isValid()) {
return (crl::now() - static_cast<crl::time>(reply.value()));
} else if (ranges::contains(NotSupportedErrors, reply.error().type())) {
NotSupported = true;
} else {
if (ranges::contains(NotSupportedErrorsToLog, reply.error().type())) {
NotSupported = true;
}
LOG(("Unable to get last user input time: %1: %2")
.arg(reply.error().name())
.arg(reply.error().message()));
}
return std::nullopt;
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
} // namespace
void SetApplicationIcon(const QIcon &icon) {
@@ -576,47 +658,12 @@ QImage GetImageFromClipboard() {
}
std::optional<crl::time> LastUserInputTime() {
// TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland
// an example: https://stackoverflow.com/q/9049087
if (!IsWayland()) {
return XCBLastUserInputTime();
}
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
static auto NotSupported = false;
if (NotSupported) {
return std::nullopt;
}
static const auto Message = QDBusMessage::createMethodCall(
qsl("org.freedesktop.ScreenSaver"),
qsl("/org/freedesktop/ScreenSaver"),
qsl("org.freedesktop.ScreenSaver"),
qsl("GetSessionIdleTime"));
const QDBusReply<uint> reply = QDBusConnection::sessionBus().call(
Message);
static const auto NotSupportedErrors = {
QDBusError::ServiceUnknown,
QDBusError::NotSupported,
};
static const auto NotSupportedErrorsToLog = {
QDBusError::Disconnected,
QDBusError::AccessDenied,
};
if (reply.isValid()) {
return (crl::now() - static_cast<crl::time>(reply.value()));
} else if (ranges::contains(NotSupportedErrors, reply.error().type())) {
NotSupported = true;
} else {
if (ranges::contains(NotSupportedErrorsToLog, reply.error().type())) {
NotSupported = true;
}
LOG(("Unable to get last user input time: %1: %2")
.arg(reply.error().name())
.arg(reply.error().message()));
}
return DBusLastUserInputTime();
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return std::nullopt;