From 6ee08faa2410626b324a53b094c3bb8458347755 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 3 Jun 2022 20:09:17 +0400 Subject: [PATCH] Migrate from kwayland to QtWaylandScanner --- .gitmodules | 6 - Telegram/CMakeLists.txt | 13 +- .../linux/linux_wayland_integration.cpp | 199 ++++++++++++++---- Telegram/ThirdParty/extra-cmake-modules | 1 - Telegram/ThirdParty/kwayland | 1 - 5 files changed, 165 insertions(+), 55 deletions(-) delete mode 160000 Telegram/ThirdParty/extra-cmake-modules delete mode 160000 Telegram/ThirdParty/kwayland diff --git a/.gitmodules b/.gitmodules index af8be44b63..1d4d04f212 100644 --- a/.gitmodules +++ b/.gitmodules @@ -85,15 +85,9 @@ [submodule "Telegram/ThirdParty/jemalloc"] path = Telegram/ThirdParty/jemalloc url = https://github.com/jemalloc/jemalloc -[submodule "Telegram/ThirdParty/kwayland"] - path = Telegram/ThirdParty/kwayland - url = https://github.com/KDE/kwayland.git [submodule "Telegram/ThirdParty/dispatch"] path = Telegram/ThirdParty/dispatch url = https://github.com/apple/swift-corelibs-libdispatch -[submodule "Telegram/ThirdParty/extra-cmake-modules"] - path = Telegram/ThirdParty/extra-cmake-modules - url = https://github.com/KDE/extra-cmake-modules.git [submodule "Telegram/ThirdParty/plasma-wayland-protocols"] path = Telegram/ThirdParty/plasma-wayland-protocols url = https://github.com/KDE/plasma-wayland-protocols.git diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 7052bd3faf..1dadeea048 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -95,7 +95,7 @@ PRIVATE desktop-app::external_xxhash ) -target_precompile_headers(Telegram PRIVATE ${src_loc}/stdafx.h) +target_precompile_headers(Telegram PRIVATE $<$:${src_loc}/stdafx.h>) nice_target_sources(Telegram ${src_loc} PRIVATE ${style_files} @@ -1436,10 +1436,19 @@ else() endif() if (NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION) + if (DESKTOP_APP_QT6) + qt6_generate_wayland_protocol_client_sources(Telegram + FILES + ${third_party_loc}/plasma-wayland-protocols/src/protocols/plasma-shell.xml + ) + else() + message(FATAL_ERROR "This piece of cmake code is not ported to Qt 5") + endif() + target_link_libraries(Telegram PRIVATE desktop-app::lib_waylandshells - desktop-app::external_kwayland + desktop-app::external_wayland_client ) endif() endif() diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index 7641579aa4..ea3d5f0cd4 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -8,52 +8,171 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/linux_wayland_integration.h" #include "base/platform/base_platform_info.h" +#include "base/qt_signal_producer.h" +#include "base/flat_map.h" +#include "qwayland-plasma-shell.h" -#include -#include -#include -#include - -using namespace KWayland::Client; +#include +#include +#include +#include namespace Platform { namespace internal { +namespace { + +struct WlRegistryDeleter { + void operator()(wl_registry *value) { + wl_registry_destroy(value); + } +}; + +struct PlasmaSurfaceDeleter { + void operator()(org_kde_plasma_surface *value) { + org_kde_plasma_surface_destroy(value); + } +}; + +template +class QtWaylandAutoDestroyer : public T { +public: + QtWaylandAutoDestroyer() = default; + + ~QtWaylandAutoDestroyer() { + if (!this->isInitialized()) { + return; + } + + static constexpr auto HasDestroy = requires(const T &t) { + t.destroy(); + }; + + if constexpr (HasDestroy) { + this->destroy(); + } else { + free(this->object()); + this->init(nullptr); + } + } +}; + +} // namespace struct WaylandIntegration::Private { - std::unique_ptr connection; - Registry registry; - std::unique_ptr plasmaShell; + org_kde_plasma_surface *plasmaSurface(QWindow *window); + std::unique_ptr registry; + QtWaylandAutoDestroyer plasmaShell; + uint32_t plasmaShellName = 0; + base::flat_map> plasmaSurfaces; + rpl::lifetime lifetime; + + static const struct wl_registry_listener RegistryListener; }; +const struct wl_registry_listener WaylandIntegration::Private::RegistryListener = { + decltype(wl_registry_listener::global)(+[]( + Private *data, + wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) { + if (interface == qstr("org_kde_plasma_shell")) { + data->plasmaShell.init(registry, name, version); + data->plasmaShellName = name; + } + }), + decltype(wl_registry_listener::global_remove)(+[]( + Private *data, + wl_registry *registry, + uint32_t name) { + if (name == data->plasmaShellName) { + free(data->plasmaShell.object()); + data->plasmaShell.init(nullptr); + data->plasmaShellName = 0; + } + }), +}; + +org_kde_plasma_surface *WaylandIntegration::Private::plasmaSurface( + QWindow *window) { + if (!plasmaShell.isInitialized()) { + return nullptr; + } + + const auto native = QGuiApplication::platformNativeInterface(); + if (!native) { + return nullptr; + } + + const auto surface = reinterpret_cast( + native->nativeResourceForWindow(QByteArray("surface"), window)); + + if (!surface) { + return nullptr; + } + + const auto it = plasmaSurfaces.find(surface); + if (it != plasmaSurfaces.cend()) { + return it->second.get(); + } + + const auto result = plasmaShell.get_surface(surface); + if (!result) { + return nullptr; + } + + plasmaSurfaces.emplace(surface, result); + + base::qt_signal_producer( + window, + &QObject::destroyed + ) | rpl::start_with_next([=] { + auto it = plasmaSurfaces.find(surface); + if (it != plasmaSurfaces.cend()) { + plasmaSurfaces.erase(it); + } + }, lifetime); + + return result; +} + WaylandIntegration::WaylandIntegration() : _private(std::make_unique()) { - _private->connection = std::unique_ptr{ - ConnectionThread::fromApplication(), - }; + const auto native = QGuiApplication::platformNativeInterface(); + if (!native) { + return; + } - _private->registry.create(_private->connection.get()); - _private->registry.setup(); + const auto display = reinterpret_cast( + native->nativeResourceForIntegration(QByteArray("wl_display"))); - QObject::connect( - _private->connection.get(), - &ConnectionThread::connectionDied, - &_private->registry, - &Registry::destroy); + if (!display) { + return; + } - QObject::connect( - &_private->registry, - &Registry::plasmaShellAnnounced, - [=](uint name, uint version) { - _private->plasmaShell = std::unique_ptr{ - _private->registry.createPlasmaShell(name, version), - }; + _private->registry.reset(wl_display_get_registry(display)); + wl_registry_add_listener( + _private->registry.get(), + &Private::RegistryListener, + _private.get()); - QObject::connect( - _private->connection.get(), - &ConnectionThread::connectionDied, - _private->plasmaShell.get(), - &PlasmaShell::destroy); - }); + base::qt_signal_producer( + native, + &QObject::destroyed + ) | rpl::start_with_next([=] { + // too late for standard destructors, just free + for (auto it = _private->plasmaSurfaces.begin() + ; it != _private->plasmaSurfaces.cend() + ; ++it) { + free(it->second.release()); + _private->plasmaSurfaces.erase(it); + } + free(_private->plasmaShell.object()); + _private->plasmaShell.init(nullptr); + free(_private->registry.release()); + }, _private->lifetime); } WaylandIntegration::~WaylandIntegration() = default; @@ -65,26 +184,16 @@ WaylandIntegration *WaylandIntegration::Instance() { } bool WaylandIntegration::skipTaskbarSupported() { - return _private->plasmaShell != nullptr; + return _private->plasmaShell.isInitialized(); } void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) { - const auto shell = _private->plasmaShell.get(); - if (!shell) { - return; - } - - const auto surface = Surface::fromWindow(window); - if (!surface) { - return; - } - - const auto plasmaSurface = shell->createSurface(surface, surface); + auto plasmaSurface = _private->plasmaSurface(window); if (!plasmaSurface) { return; } - plasmaSurface->setSkipTaskbar(skip); + org_kde_plasma_surface_set_skip_taskbar(plasmaSurface, skip); } } // namespace internal diff --git a/Telegram/ThirdParty/extra-cmake-modules b/Telegram/ThirdParty/extra-cmake-modules deleted file mode 160000 index eccf695824..0000000000 --- a/Telegram/ThirdParty/extra-cmake-modules +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eccf695824fa931bca471bad3f1aa3a1f244fdd6 diff --git a/Telegram/ThirdParty/kwayland b/Telegram/ThirdParty/kwayland deleted file mode 160000 index 15af039af2..0000000000 --- a/Telegram/ThirdParty/kwayland +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 15af039af2044c7a2d7cfea0d2c1a99bf6c151ac