diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 391e91daa..bd0322afc 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -84,6 +84,13 @@ if (LINUX) ) endif() + if (NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION) + target_link_libraries(Telegram + PRIVATE + desktop-app::external_kwayland + ) + endif() + if (DESKTOP_APP_USE_PACKAGED AND NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION AND Qt5WaylandClient_VERSION VERSION_LESS 5.13.0) diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index e6af77b70..baefa943b 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -15,11 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#include +#include + #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) && !defined DESKTOP_APP_QT_PATCHED #include #endif // Qt < 5.13 && !DESKTOP_APP_QT_PATCHED using QtWaylandClient::QWaylandWindow; +using namespace KWayland::Client; namespace Platform { namespace internal { @@ -51,15 +55,75 @@ enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) { } // namespace -WaylandIntegration::WaylandIntegration() { +class WaylandIntegration::Private : public QObject { +public: + Private(); + + [[nodiscard]] Registry ®istry() { + return _registry; + } + + [[nodiscard]] QEventLoop &interfacesLoop() { + return _interfacesLoop; + } + + [[nodiscard]] bool interfacesAnnounced() const { + return _interfacesAnnounced; + } + +private: + ConnectionThread _connection; + Registry _registry; + QEventLoop _interfacesLoop; + bool _interfacesAnnounced = false; +}; + +WaylandIntegration::Private::Private() { + connect(&_connection, &ConnectionThread::connected, [=] { + LOG(("Successfully connected to Wayland server at socket: %1") + .arg(_connection.socketName())); + + _registry.create(&_connection); + _registry.setup(); + }); + + connect( + &_connection, + &ConnectionThread::connectionDied, + &_registry, + &Registry::destroy); + + connect(&_registry, &Registry::interfacesAnnounced, [=] { + _interfacesAnnounced = true; + _interfacesLoop.quit(); + }); + + _connection.initConnection(); } +WaylandIntegration::WaylandIntegration() +: _private(std::make_unique()) { +} + +WaylandIntegration::~WaylandIntegration() = default; + WaylandIntegration *WaylandIntegration::Instance() { if (!IsWayland()) return nullptr; static WaylandIntegration instance; return &instance; } +void WaylandIntegration::waitForInterfaceAnnounce() { + if (!_private->interfacesAnnounced()) { + _private->interfacesLoop().exec(); + } +} + +bool WaylandIntegration::supportsXdgDecoration() { + return _private->registry().hasInterface( + Registry::Interface::XdgDecorationUnstableV1); +} + bool WaylandIntegration::startMove(QWindow *window) { // There are startSystemMove on Qt 5.15 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) && !defined DESKTOP_APP_QT_PATCHED diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h index 73486fef7..a6e582042 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h @@ -15,12 +15,18 @@ namespace internal { class WaylandIntegration { public: static WaylandIntegration *Instance(); + void waitForInterfaceAnnounce(); + bool supportsXdgDecoration(); bool startMove(QWindow *window); bool startResize(QWindow *window, Qt::Edges edges); bool showWindowMenu(QWindow *window); private: WaylandIntegration(); + ~WaylandIntegration(); + + class Private; + const std::unique_ptr _private; }; } // namespace internal diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp index e79fd2d95..7a5b52e96 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp @@ -12,15 +12,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace internal { +class WaylandIntegration::Private { +}; + WaylandIntegration::WaylandIntegration() { } +WaylandIntegration::~WaylandIntegration() = default; + WaylandIntegration *WaylandIntegration::Instance() { if (!IsWayland()) return nullptr; static WaylandIntegration instance; return &instance; } +void WaylandIntegration::waitForInterfaceAnnounce() { +} + +bool WaylandIntegration::supportsXdgDecoration() { + return false; +} + bool WaylandIntegration::startMove(QWindow *window) { return false; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 85800979d..5eac9bd28 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -1226,6 +1226,11 @@ void start() { Libs::start(); MainWindow::LibsLoaded(); + + // wait for interface announce to know if native window frame is supported + if (const auto waylandIntegration = WaylandIntegration::Instance()) { + waylandIntegration->waitForInterfaceAnnounce(); + } } void finish() { diff --git a/Telegram/SourceFiles/platform/linux/window_title_linux.cpp b/Telegram/SourceFiles/platform/linux/window_title_linux.cpp index 95e8b6449..bd990755c 100644 --- a/Telegram/SourceFiles/platform/linux/window_title_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/window_title_linux.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/linux/window_title_linux.h" -#include "platform/linux/linux_desktop_environment.h" +#include "platform/linux/linux_wayland_integration.h" #include "base/platform/base_platform_info.h" namespace Platform { @@ -24,9 +24,10 @@ bool SystemMoveResizeSupported() { } // namespace bool AllowNativeWindowFrameToggle() { + const auto waylandIntegration = internal::WaylandIntegration::Instance(); return SystemMoveResizeSupported() - // https://gitlab.gnome.org/GNOME/mutter/-/issues/217 - && !(DesktopEnvironment::IsGnome() && IsWayland()); + && (!waylandIntegration + || waylandIntegration->supportsXdgDecoration()); } object_ptr CreateTitleWidget(QWidget *parent) { diff --git a/Telegram/build/docker/centos_env/Dockerfile b/Telegram/build/docker/centos_env/Dockerfile index ae13b7df6..ef88c6941 100644 --- a/Telegram/build/docker/centos_env/Dockerfile +++ b/Telegram/build/docker/centos_env/Dockerfile @@ -1,12 +1,14 @@ FROM centos:7 AS builder ENV GIT https://github.com -ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig +ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/usr/local/share/pkgconfig ENV QT 5_15_2 ENV QT_TAG v5.15.2 ENV QT_PREFIX /usr/local/desktop-app/Qt-5.15.2 ENV OPENSSL_VER 1_1_1 ENV OPENSSL_PREFIX /usr/local/desktop-app/openssl-1.1.1 +ENV PATH ${PATH}:${QT_PREFIX}/bin +ENV Qt5_DIR ${QT_PREFIX} RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm RUN yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm @@ -30,6 +32,18 @@ FROM builder AS patches ADD https://api.github.com/repos/desktop-app/patches/git/refs/heads/master patches-version.json RUN git clone --depth=1 $GIT/desktop-app/patches.git +FROM builder AS extra-cmake-modules + +RUN git clone -b v5.77.0 --depth=1 $GIT/KDE/extra-cmake-modules.git + +WORKDIR extra-cmake-modules +RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF +RUN cmake3 --build build -j$(nproc) +RUN DESTDIR="$LibrariesPath/extra-cmake-modules-cache" cmake3 --install build + +WORKDIR .. +RUN rm -rf extra-cmake-modules + FROM builder AS libffi RUN git clone -b v3.3 --depth=1 $GIT/libffi/libffi.git @@ -203,6 +217,32 @@ RUN make DESTDIR="$LibrariesPath/wayland-cache" install WORKDIR .. RUN rm -rf wayland +FROM builder AS wayland-protocols +COPY --from=wayland ${LibrariesPath}/wayland-cache / + +RUN git clone -b 1.18 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols.git + +WORKDIR wayland-protocols +RUN ./autogen.sh +RUN make -j$(nproc) +RUN make DESTDIR="$LibrariesPath/wayland-protocols-cache" install + +WORKDIR .. +RUN rm -rf wayland-protocols + +FROM builder AS plasma-wayland-protocols +COPY --from=extra-cmake-modules ${LibrariesPath}/extra-cmake-modules-cache / + +RUN git clone -b v1.1.1 --depth=1 $GIT/KDE/plasma-wayland-protocols.git + +WORKDIR plasma-wayland-protocols +RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release +RUN cmake3 --build build -j$(nproc) +RUN DESTDIR="$LibrariesPath/plasma-wayland-protocols-cache" cmake3 --install build + +WORKDIR .. +RUN rm -rf plasma-wayland-protocols + FROM builder AS libva COPY --from=libffi ${LibrariesPath}/libffi-cache / @@ -452,6 +492,34 @@ RUN make INSTALL_ROOT="$LibrariesPath/qt-cache" install WORKDIR .. RUN rm -rf qt_${QT} +FROM builder AS kwayland + +COPY --from=extra-cmake-modules ${LibrariesPath}/extra-cmake-modules-cache / +COPY --from=libffi ${LibrariesPath}/libffi-cache / +COPY --from=mozjpeg ${LibrariesPath}/mozjpeg-cache / +COPY --from=xcb ${LibrariesPath}/xcb-cache / +COPY --from=xcb-wm ${LibrariesPath}/xcb-wm-cache / +COPY --from=xcb-util ${LibrariesPath}/xcb-util-cache / +COPY --from=xcb-image ${LibrariesPath}/xcb-image-cache / +COPY --from=xcb-keysyms ${LibrariesPath}/xcb-keysyms-cache / +COPY --from=xcb-render-util ${LibrariesPath}/xcb-render-util-cache / +COPY --from=wayland ${LibrariesPath}/wayland-cache / +COPY --from=wayland-protocols ${LibrariesPath}/wayland-protocols-cache / +COPY --from=plasma-wayland-protocols ${LibrariesPath}/plasma-wayland-protocols-cache / +COPY --from=openssl ${LibrariesPath}/openssl-cache / +COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache / +COPY --from=qt ${LibrariesPath}/qt-cache / + +RUN git clone -b v5.77.0 --depth=1 $GIT/KDE/kwayland.git + +WORKDIR kwayland +RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF +RUN cmake3 --build build -j$(nproc) +RUN DESTDIR="$LibrariesPath/kwayland-cache" cmake3 --install build + +WORKDIR .. +RUN rm -rf kwayland + FROM patches AS breakpad RUN git clone https://chromium.googlesource.com/breakpad/breakpad.git @@ -547,6 +615,7 @@ COPY --from=openal ${LibrariesPath}/openal-cache / COPY --from=openssl ${LibrariesPath}/openssl-cache / COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache / COPY --from=qt ${LibrariesPath}/qt-cache / +COPY --from=kwayland ${LibrariesPath}/kwayland-cache / COPY --from=breakpad ${LibrariesPath}/breakpad breakpad COPY --from=breakpad ${LibrariesPath}/breakpad-cache / COPY --from=webrtc ${LibrariesPath}/tg_owt tg_owt diff --git a/cmake b/cmake index 220835876..561273a2f 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 220835876580f1df072c469e6c4dd746131a2293 +Subproject commit 561273a2f88306072750283b28d763959cd58652 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f4f447143..67d54c356 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -74,6 +74,7 @@ parts: - libasound2-dev - libglib2.0-dev - libgtk-3-dev + - libkf5wayland-dev - liblzma-dev - libopus-dev - libpulse-dev @@ -90,6 +91,7 @@ parts: - libasound2 - libglib2.0-0 - libgtk-3-0 + - libkf5waylandclient5 - liblzma5 - libopus0 - libpulse0