From 4c48722c59cad129e59ba3f977284e8f324c34cd Mon Sep 17 00:00:00 2001 From: David Redondo Date: Fri, 7 Jul 2023 13:23:51 +0200 Subject: [PATCH] Provide a system bell implementation on wayland --- CMakeLists.txt | 2 +- src/plugins/systembell/systembell.cpp | 41 +++++++++++++++- src/plugins/systembell/systembell.h | 5 ++ src/wayland/CMakeLists.txt | 6 +++ src/wayland/xdgsystembell_v1.cpp | 67 +++++++++++++++++++++++++++ src/wayland/xdgsystembell_v1.h | 37 +++++++++++++++ 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/wayland/xdgsystembell_v1.cpp create mode 100644 src/wayland/xdgsystembell_v1.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 652591120f..2d2073ce59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,7 +212,7 @@ else() set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 0) endif() -find_package(WaylandProtocols 1.36) +find_package(WaylandProtocols 1.38) set_package_properties(WaylandProtocols PROPERTIES TYPE REQUIRED PURPOSE "Collection of Wayland protocols that add functionality not available in the Wayland core protocol" diff --git a/src/plugins/systembell/systembell.cpp b/src/plugins/systembell/systembell.cpp index 6dc4b0483f..3305b852bf 100644 --- a/src/plugins/systembell/systembell.cpp +++ b/src/plugins/systembell/systembell.cpp @@ -12,6 +12,10 @@ #include "effect/effecthandler.h" #include "opengl/glshader.h" #include "opengl/glshadermanager.h" +#include "wayland/surface.h" +#include "wayland/xdgsystembell_v1.h" +#include "wayland_server.h" +#include "window.h" #include #include @@ -31,6 +35,9 @@ static void ensureResources() namespace KWin { +QTimer *SystemBellEffect::s_systemBellRemoveTimer = nullptr; +XdgSystemBellV1Interface *SystemBellEffect::s_systemBell = nullptr; + SystemBellEffect::SystemBellEffect() : m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("kaccessrc"))) , m_kdeglobals(QStringLiteral("kdeglobals")) @@ -67,6 +74,31 @@ SystemBellEffect::SystemBellEffect() qCWarning(KWIN_SYSTEMBELL) << "Failed to set application properties on canberra context for audio notification:" << ca_strerror(ret); } } + + if (waylandServer()) { + if (!s_systemBellRemoveTimer) { + s_systemBellRemoveTimer = new QTimer(QCoreApplication::instance()); + s_systemBellRemoveTimer->setSingleShot(true); + s_systemBellRemoveTimer->callOnTimeout([]() { + s_systemBell->remove(); + s_systemBell = nullptr; + }); + } + s_systemBellRemoveTimer->stop(); + if (!s_systemBell) { + s_systemBell = new XdgSystemBellV1Interface(waylandServer()->display(), s_systemBellRemoveTimer); + connect(s_systemBell, &XdgSystemBellV1Interface::ringSurface, this, [this](SurfaceInterface *surface) { + triggerWindow(effects->findWindow(surface)); + }); + connect(s_systemBell, &XdgSystemBellV1Interface::ring, this, [this](ClientConnection *client) { + if (effects->activeWindow()) { + if (effects->activeWindow()->surface() && effects->activeWindow()->surface()->client() == client) { + triggerWindow(effects->activeWindow()); + } + } + }); + } + } } SystemBellEffect::~SystemBellEffect() @@ -74,6 +106,10 @@ SystemBellEffect::~SystemBellEffect() if (m_caContext) { ca_context_destroy(m_caContext); } + // When compositing is restarted, avoid removing the system bell immediately + if (s_systemBell) { + s_systemBellRemoveTimer->start(1000); + } } void SystemBellEffect::reconfigure(ReconfigureFlags flags) @@ -169,8 +205,11 @@ void SystemBellEffect::triggerScreen() void SystemBellEffect::triggerWindow() { - const auto window = effects->activeWindow(); + triggerWindow(effects->activeWindow()); +} +void SystemBellEffect::triggerWindow(EffectWindow *window) +{ if (!window || m_windows.contains(window)) { return; } diff --git a/src/plugins/systembell/systembell.h b/src/plugins/systembell/systembell.h index e4bc8c4829..2417f91c5f 100644 --- a/src/plugins/systembell/systembell.h +++ b/src/plugins/systembell/systembell.h @@ -20,6 +20,7 @@ namespace KWin { class GLShader; +class XdgSystemBellV1Interface; class SystemBellEffect : public OffscreenEffect { @@ -52,6 +53,7 @@ private: Color, }; + void triggerWindow(EffectWindow *window); void flash(EffectWindow *window); void unflash(EffectWindow *window); void loadConfig(const KConfigGroup &group); @@ -73,6 +75,9 @@ private: KConfigWatcher::Ptr m_configWatcher; KConfig m_kdeglobals; KConfigGroup m_bellConfig; + + static QTimer *s_systemBellRemoveTimer; + static XdgSystemBellV1Interface *s_systemBell; }; inline int SystemBellEffect::requestedEffectChainPosition() const diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index c25ae07f2e..ff9e8ad45b 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -305,6 +305,10 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml PROTOCOL ${WaylandProtocols_DATADIR}/staging/alpha-modifier/alpha-modifier-v1.xml BASENAME alpha-modifier-v1 ) +ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml + PROTOCOL ${WaylandProtocols_DATADIR}/staging/xdg-system-bell/xdg-system-bell-v1.xml + BASENAME xdg-system-bell-v1 +) target_sources(kwin PRIVATE abstract_data_source.cpp @@ -387,6 +391,7 @@ target_sources(kwin PRIVATE xdgforeign_v2.cpp xdgoutput_v1.cpp xdgshell.cpp + xdgsystembell_v1.cpp xdgtopleveldrag_v1.cpp xwaylandkeyboardgrab_v1.cpp xwaylandshell_v1.cpp @@ -466,6 +471,7 @@ install(FILES xdgforeign_v2.h xdgoutput_v1.h xdgshell.h + xdgsystembell_v1.h xwaylandkeyboardgrab_v1.h xwaylandshell_v1.h xx_colormanagement_v4.h diff --git a/src/wayland/xdgsystembell_v1.cpp b/src/wayland/xdgsystembell_v1.cpp new file mode 100644 index 0000000000..6adb24f115 --- /dev/null +++ b/src/wayland/xdgsystembell_v1.cpp @@ -0,0 +1,67 @@ +/* + SPDX-FileCopyrightText: 2023 David Redondo + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#include "xdgsystembell_v1.h" + +#include "clientconnection.h" +#include "display.h" +#include "surface.h" + +#include + +namespace KWin +{ + +static constexpr int version = 1; + +class XdgSystemBellV1InterfacePrivate : public QtWaylandServer::xdg_system_bell_v1 +{ +public: + XdgSystemBellV1InterfacePrivate(XdgSystemBellV1Interface *q, Display *display); + + XdgSystemBellV1Interface *q; + Display *display; + +protected: + void xdg_system_bell_v1_ring(Resource *resource, wl_resource *surface) override; + void xdg_system_bell_v1_destroy(Resource *resource) override; +}; + +XdgSystemBellV1InterfacePrivate::XdgSystemBellV1InterfacePrivate(XdgSystemBellV1Interface *q, Display *display) + : QtWaylandServer::xdg_system_bell_v1(*display, version) + , q(q) + , display(display) +{ +} + +void XdgSystemBellV1InterfacePrivate::xdg_system_bell_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void XdgSystemBellV1InterfacePrivate::xdg_system_bell_v1_ring(Resource *resource, wl_resource *surface_resource) +{ + if (surface_resource) { + auto surface = SurfaceInterface::get(surface_resource); + Q_EMIT q->ringSurface(surface); + return; + } + Q_EMIT q->ring(display->getConnection(resource->client())); +} + +XdgSystemBellV1Interface::XdgSystemBellV1Interface(Display *display, QObject *parent) + : QObject(parent) + , d(std::make_unique(this, display)) +{ +} + +XdgSystemBellV1Interface::~XdgSystemBellV1Interface() = default; + +void XdgSystemBellV1Interface::remove() +{ + d->globalRemove(); +} +} diff --git a/src/wayland/xdgsystembell_v1.h b/src/wayland/xdgsystembell_v1.h new file mode 100644 index 0000000000..d689e3ce93 --- /dev/null +++ b/src/wayland/xdgsystembell_v1.h @@ -0,0 +1,37 @@ +/* + SPDX-FileCopyrightText: 2023 David Redondo + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#pragma once + +#include "kwin_export.h" + +#include + +#include + +namespace KWin +{ +class ClientConnection; +class Display; +class SurfaceInterface; +class XdgSystemBellV1InterfacePrivate; + +class KWIN_EXPORT XdgSystemBellV1Interface : public QObject +{ + Q_OBJECT +public: + XdgSystemBellV1Interface(Display *display, QObject *parent = nullptr); + ~XdgSystemBellV1Interface(); + + void remove(); +Q_SIGNALS: + void ring(ClientConnection *client); + void ringSurface(SurfaceInterface *surface); + +private: + std::unique_ptr d; +}; +}