diff --git a/CMakeLists.txt b/CMakeLists.txt index 54048a445..8e21e949d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,7 @@ protocolnew("staging/security-context" "security-context-v1" false) protocolnew("staging/content-type" "content-type-v1" false) protocolnew("staging/color-management" "color-management-v1" false) protocolnew("staging/xdg-toplevel-tag" "xdg-toplevel-tag-v1" false) +protocolnew("staging/xdg-system-bell" "xdg-system-bell-v1" false) protocolwayland() diff --git a/protocols/meson.build b/protocols/meson.build index a0cad39be..348ce8a3f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -74,6 +74,7 @@ protocols = [ wayland_protocol_dir / 'staging/content-type/content-type-v1.xml', wayland_protocol_dir / 'staging/color-management/color-management-v1.xml', wayland_protocol_dir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml', + wayland_protocol_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml', ] wl_protocols = [] diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 8ebe80107..7f51d09f9 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -61,6 +61,7 @@ #include "../protocols/FrogColorManagement.hpp" #include "../protocols/ContentType.hpp" #include "../protocols/XDGTag.hpp" +#include "../protocols/XDGBell.hpp" #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" @@ -186,6 +187,7 @@ CProtocolManager::CProtocolManager() { PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface"); PROTO::contentType = makeUnique(&wp_content_type_manager_v1_interface, 1, "ContentType"); PROTO::xdgTag = makeUnique(&xdg_toplevel_tag_manager_v1_interface, 1, "XDGTag"); + PROTO::xdgBell = makeUnique(&xdg_system_bell_v1_interface, 1, "XDGBell"); if (*PENABLECM) PROTO::colorManagement = makeUnique(&wp_color_manager_v1_interface, 1, "ColorManagement", *PDEBUGCM); @@ -277,6 +279,7 @@ CProtocolManager::~CProtocolManager() { PROTO::xxColorManagement.reset(); PROTO::frogColorManagement.reset(); PROTO::xdgTag.reset(); + PROTO::xdgBell.reset(); PROTO::lease.reset(); PROTO::sync.reset(); @@ -329,11 +332,12 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { PROTO::primarySelection->getGlobal(), PROTO::hyprlandSurface->getGlobal(), PROTO::xdgTag->getGlobal(), + PROTO::xdgBell->getGlobal(), PROTO::sync ? PROTO::sync->getGlobal() : nullptr, PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, }; // clang-format on - return std::find(ALLOWED_WHITELIST.begin(), ALLOWED_WHITELIST.end(), global) == ALLOWED_WHITELIST.end(); + return std::ranges::find(ALLOWED_WHITELIST, global) == ALLOWED_WHITELIST.end(); } diff --git a/src/protocols/XDGBell.cpp b/src/protocols/XDGBell.cpp new file mode 100644 index 000000000..42fd60403 --- /dev/null +++ b/src/protocols/XDGBell.cpp @@ -0,0 +1,64 @@ +#include "XDGBell.hpp" +#include "XDGShell.hpp" +#include "../desktop/Window.hpp" +#include "../managers/EventManager.hpp" +#include "../Compositor.hpp" + +CXDGSystemBellManagerResource::CXDGSystemBellManagerResource(UP&& resource) : m_resource(std::move(resource)) { + if UNLIKELY (!good()) + return; + + m_resource->setDestroy([this](CXdgSystemBellV1* r) { PROTO::xdgBell->destroyResource(this); }); + m_resource->setOnDestroy([this](CXdgSystemBellV1* r) { PROTO::xdgBell->destroyResource(this); }); + + resource->setRing([](CXdgSystemBellV1* r, wl_resource* toplevel) { + auto TOPLEVEL = CXDGToplevelResource::fromResource(toplevel); + + if (!TOPLEVEL) { + g_pEventManager->postEvent(SHyprIPCEvent{ + .event = "bell", + .data = "", + }); + return; + } + + for (const auto& w : g_pCompositor->m_windows) { + if (!w->m_isMapped || w->m_isX11 || !w->m_xdgSurface) + continue; + + if (w->m_xdgSurface == TOPLEVEL->owner) { + g_pEventManager->postEvent(SHyprIPCEvent{ + .event = "bell", + .data = std::format("{:x}", (uintptr_t)w.get()), + }); + return; + } + } + + g_pEventManager->postEvent(SHyprIPCEvent{ + .event = "bell", + .data = "", + }); + }); +} + +bool CXDGSystemBellManagerResource::good() { + return m_resource->resource(); +} + +CXDGSystemBellProtocol::CXDGSystemBellProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CXDGSystemBellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = WP{m_vManagers.emplace_back(makeUnique(makeUnique(client, ver, id)))}; + + if UNLIKELY (!RESOURCE->good()) { + wl_client_post_no_memory(client); + return; + } +} + +void CXDGSystemBellProtocol::destroyResource(CXDGSystemBellManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} diff --git a/src/protocols/XDGBell.hpp b/src/protocols/XDGBell.hpp new file mode 100644 index 000000000..ff3850597 --- /dev/null +++ b/src/protocols/XDGBell.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include "WaylandProtocol.hpp" +#include "xdg-system-bell-v1.hpp" + +class CXDGSystemBellManagerResource { + public: + CXDGSystemBellManagerResource(UP&& resource); + + bool good(); + + private: + UP m_resource; +}; + +class CXDGSystemBellProtocol : public IWaylandProtocol { + public: + CXDGSystemBellProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CXDGSystemBellManagerResource* res); + + // + std::vector> m_vManagers; + + friend class CXDGSystemBellManagerResource; +}; + +namespace PROTO { + inline UP xdgBell; +};