From 59b521d666a69a5ed56c3c29be056fb05b5bf68a Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 10 Jul 2020 16:51:30 +0400 Subject: [PATCH] Implement xcb-based LastUserInputTime method --- .github/workflows/linux.yml | 2 +- Telegram/CMakeLists.txt | 17 +++ .../platform/linux/specific_linux.cpp | 127 ++++++++++++------ docs/building-cmake.md | 2 +- snap/snapcraft.yaml | 4 + 5 files changed, 110 insertions(+), 42 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index a3a2744d0f..cb249cbf16 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -95,7 +95,7 @@ jobs: libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ - libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ + libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-screensaver0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 385ba580d1..4463fd890c 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -127,6 +127,23 @@ PRIVATE desktop-app::external_openal ) +if (LINUX) + if (DESKTOP_APP_USE_PACKAGED) + find_package(PkgConfig REQUIRED) + pkg_check_modules(XCB_SCREENSAVER REQUIRED IMPORTED_TARGET xcb-screensaver) + pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb) + + target_link_libraries(Telegram + PRIVATE + PkgConfig::XCB_SCREENSAVER + PkgConfig::XCB + ) + else() + target_link_static_libraries(Telegram PRIVATE xcb-screensaver) + target_link_libraries(Telegram PRIVATE xcb) + endif() +endif() + if (LINUX AND NOT TDESKTOP_DISABLE_GTK_INTEGRATION) find_package(PkgConfig REQUIRED) target_compile_options(Telegram PRIVATE -Wno-register) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 931e342ff0..a0bd14b9e5 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -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 #include #include +#include #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include @@ -32,6 +34,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#include +#include + #include #include #include @@ -268,6 +273,83 @@ bool GenerateDesktopFile( } } +std::optional XCBLastUserInputTime() { + if (const auto native = QGuiApplication::platformNativeInterface()) { + const auto connection = reinterpret_cast( + 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(idle)); + } + + return std::nullopt; +} + +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +std::optional 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 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(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 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 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(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; diff --git a/docs/building-cmake.md b/docs/building-cmake.md index c72c899135..019a5f0147 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -17,7 +17,7 @@ You will need GCC 8 installed. To install them and all the required dependencies libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ - libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ + libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-screensaver0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index b66cb0739f..6a00e3c864 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -79,6 +79,8 @@ parts: - libqt5waylandclient5-dev - libqt5x11extras5-dev - libssl-dev + - libxcb1-dev + - libxcb-screensaver0-dev - zlib1g-dev stage-packages: - qt5-image-formats-plugins @@ -92,6 +94,8 @@ parts: - libqt5waylandclient5 - libqt5x11extras5 - libssl1.1 + - libxcb1 + - libxcb-screensaver0 - zlib1g cmake-parameters: - -DCMAKE_BUILD_TYPE=Release