From 434ef343789fd71166caa8c67fd57652580c348b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 13 May 2021 06:38:30 +0400 Subject: [PATCH] Implement taskbar icon hidding on Wayland with org_kde_plasma_shell protocol --- .../linux/linux_wayland_integration.cpp | 44 +++++++++++++++++++ .../linux/linux_wayland_integration.h | 2 + .../linux/linux_wayland_integration_dummy.cpp | 7 +++ .../platform/linux/main_window_linux.cpp | 27 +++++++----- .../platform/linux/specific_linux.cpp | 10 ++++- 5 files changed, 76 insertions(+), 14 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index 33eecd74c..ba521184b 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include using namespace KWayland::Client; @@ -31,6 +32,10 @@ public: return _xdgExporter.get(); } + [[nodiscard]] PlasmaShell *plasmaShell() { + return _plasmaShell.get(); + } + [[nodiscard]] QEventLoop &interfacesLoop() { return _interfacesLoop; } @@ -45,6 +50,7 @@ private: Registry _registry; Registry _applicationRegistry; std::unique_ptr _xdgExporter; + std::unique_ptr _plasmaShell; QEventLoop _interfacesLoop; bool _interfacesAnnounced = false; }; @@ -96,6 +102,21 @@ WaylandIntegration::Private::Private() &XdgExporter::destroy); }); + connect( + &_applicationRegistry, + &Registry::plasmaShellAnnounced, + [=](uint name, uint version) { + _plasmaShell = std::unique_ptr{ + _applicationRegistry.createPlasmaShell(name, version), + }; + + connect( + _applicationConnection, + &ConnectionThread::connectionDied, + _plasmaShell.get(), + &PlasmaShell::destroy); + }); + _connection.initConnection(); } @@ -143,5 +164,28 @@ QString WaylandIntegration::nativeHandle(QWindow *window) { return {}; } +bool WaylandIntegration::skipTaskbarSupported() { + return _private->plasmaShell(); +} + +void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) { + const auto shell = _private->plasmaShell(); + if (!shell) { + return; + } + + const auto surface = Surface::fromWindow(window); + if (!surface) { + return; + } + + const auto plasmaSurface = shell->createSurface(surface, surface); + if (!plasmaSurface) { + return; + } + + plasmaSurface->setSkipTaskbar(skip); +} + } // namespace internal } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h index a41d34209..d762ef9f9 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h @@ -16,6 +16,8 @@ public: void waitForInterfaceAnnounce(); bool supportsXdgDecoration(); QString nativeHandle(QWindow *window); + bool skipTaskbarSupported(); + void skipTaskbar(QWindow *window, bool skip); private: WaylandIntegration(); diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp index 2b4068553..74e6485dc 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp @@ -37,5 +37,12 @@ QString WaylandIntegration::nativeHandle(QWindow *window) { return {}; } +bool WaylandIntegration::skipTaskbarSupported() { + return false; +} + +void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) { +} + } // namespace internal } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index c6a9f6dae..7b54cc701 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_window.h" #include "platform/linux/specific_linux.h" +#include "platform/linux/linux_wayland_integration.h" #include "history/history.h" #include "history/history_widget.h" #include "history/history_inner_widget.h" @@ -59,6 +60,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace { +using internal::WaylandIntegration; + constexpr auto kPanelTrayIconName = "telegram-panel"_cs; constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs; constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs; @@ -83,15 +86,15 @@ QIcon TrayIcon; QString TrayIconThemeName, TrayIconName; #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION -bool XCBSkipTaskbar(QWindow *window, bool set) { +void XCBSkipTaskbar(QWindow *window, bool skip) { const auto connection = base::Platform::XCB::GetConnectionFromQt(); if (!connection) { - return false; + return; } const auto root = base::Platform::XCB::GetRootWindowFromQt(); if (!root.has_value()) { - return false; + return; } const auto stateAtom = base::Platform::XCB::GetAtom( @@ -99,7 +102,7 @@ bool XCBSkipTaskbar(QWindow *window, bool set) { "_NET_WM_STATE"); if (!stateAtom.has_value()) { - return false; + return; } const auto skipTaskbarAtom = base::Platform::XCB::GetAtom( @@ -107,7 +110,7 @@ bool XCBSkipTaskbar(QWindow *window, bool set) { "_NET_WM_STATE_SKIP_TASKBAR"); if (!skipTaskbarAtom.has_value()) { - return false; + return; } xcb_client_message_event_t xev; @@ -116,7 +119,7 @@ bool XCBSkipTaskbar(QWindow *window, bool set) { xev.sequence = 0; xev.window = window->winId(); xev.format = 32; - xev.data.data32[0] = set ? 1 : 0; + xev.data.data32[0] = skip ? 1 : 0; xev.data.data32[1] = *skipTaskbarAtom; xev.data.data32[2] = 0; xev.data.data32[3] = 0; @@ -129,19 +132,19 @@ bool XCBSkipTaskbar(QWindow *window, bool set) { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, reinterpret_cast(&xev)); - - return true; } #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION -bool SkipTaskbar(QWindow *window, bool set) { +void SkipTaskbar(QWindow *window, bool skip) { + if (const auto integration = WaylandIntegration::Instance()) { + integration->skipTaskbar(window, skip); + } + #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION if (IsX11()) { - return XCBSkipTaskbar(window, set); + XCBSkipTaskbar(window, skip); } #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION - - return false; } QString GetPanelIconName(int counter, bool muted) { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 971bf3a50..498b37372 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -644,9 +644,15 @@ bool TrayIconSupported() { } bool SkipTaskbarSupported() { + if (const auto integration = WaylandIntegration::Instance()) { + return integration->skipTaskbarSupported(); + } + #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION - return IsX11() - && base::Platform::XCB::IsSupportedByWM("_NET_WM_STATE_SKIP_TASKBAR"); + if (IsX11()) { + return base::Platform::XCB::IsSupportedByWM( + "_NET_WM_STATE_SKIP_TASKBAR"); + } #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION return false;