Repository: hyprwm/xdg-desktop-portal-hyprland
Pull request #322: Implement hyprland-toplevel-mapping-v1 protocol
Author: login: WhySoBad
Created: 2025-03-28T19:09:21Z | Merged: 2025-04-28T20:22:05Z

Implementation of the hyprland-toplevel-mapping-v1 protocol introduced in https://github.com/hyprwm/hyprland-protocols/pull/16

The `XDPH_WINDOW_SHARING_LIST` environment variable for share pickers now includes a `[HA>]` part containing the full 64bit address of the window associated with the toplevel. 

There can be the case where a share picker is opened just before the window address mapping for a client is received, in this case the `[HA>]` is a nullptr. I think this behavior is acceptable since the chance for this is very low and it shouldn't break anything should the `[HA>]` be zero. Alternatively, we could
- exclude the toplevel from the list for the share picker or
- wait for the `window_address` event of every toplevel (what to do in the `failed` case?)


Diff:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 871ca3c5..335014ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -130,7 +130,10 @@ protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
             true)
 protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
             true)
+protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-mapping-v1"
+        true)
 protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
+protocolnew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1" false)
 
 # Installation
 install(TARGETS hyprland-share-picker)
diff --git a/hyprland-share-picker/main.cpp b/hyprland-share-picker/main.cpp
index a3611389..1f6e131d 100644
--- a/hyprland-share-picker/main.cpp
+++ b/hyprland-share-picker/main.cpp
@@ -61,13 +61,17 @@ std::vector<SWindowEntry> getWindows(const char* env) {
         const auto TITLESEPPOS = rolling.find("[HE>]");
         const auto TITLESTR    = rolling.substr(CLASSSEPPOS + 5, TITLESEPPOS - 5 - CLASSSEPPOS);
 
+        // window address
+        const auto WINDOWSEPPOS = rolling.find("[HA>]");
+        const auto WINDOWADDR = rolling.substr(TITLESEPPOS + 5, WINDOWSEPPOS - 5 - TITLESEPPOS);
+
         try {
             result.push_back({TITLESTR, CLASSSTR, std::stoull(IDSTR)});
         } catch (std::exception& e) {
             // silent err
         }
 
-        rolling = rolling.substr(TITLESEPPOS + 5);
+        rolling = rolling.substr(WINDOWSEPPOS + 5);
     }
 
     return result;
diff --git a/protocols/meson.build b/protocols/meson.build
index f10d4c84..de23510c 100644
--- a/protocols/meson.build
+++ b/protocols/meson.build
@@ -4,7 +4,7 @@ wayland_protos = dependency('wayland-protocols',
 )
 
 hyprland_protos = dependency('hyprland-protocols',
-	version: '>=0.2',
+	version: '>=0.6.4',
 	fallback: 'hyprland-protocols',
 )
 
@@ -21,8 +21,10 @@ client_protocols = [
 	'wlr-screencopy-unstable-v1.xml',
 	'wlr-foreign-toplevel-management-unstable-v1.xml',
 	hl_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
+	hl_protocol_dir / 'protocols/hyprland-toplevel-mapping-v1.xml',
 	hl_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
 	wl_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
+	wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
 ]
 
 wl_proto_files = []
diff --git a/src/core/PortalManager.cpp b/src/core/PortalManager.cpp
index 91118709..8ae1f55a 100644
--- a/src/core/PortalManager.cpp
+++ b/src/core/PortalManager.cpp
@@ -192,6 +192,11 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
         if (!std::any_cast<Hyprlang::INT>(m_sConfig.config->getConfigValue("general:toplevel_dynamic_bind")))
             m_sHelpers.toplevel->activate();
     }
+
+    else if (INTERFACE == hyprland_toplevel_mapping_manager_v1_interface.name) {
+        m_sHelpers.toplevelMapping = std::make_unique<CToplevelMappingManager>(makeShared<CCHyprlandToplevelMappingManagerV1>(
+            (wl_proxy*)wl_registry_bind((wl_registry*)m_sWaylandConnection.registry->resource(), name, &hyprland_toplevel_mapping_manager_v1_interface, version)));
+    }
 }
 
 void CPortalManager::onGlobalRemoved(uint32_t name) {
diff --git a/src/core/PortalManager.hpp b/src/core/PortalManager.hpp
index e0f2f031..bf74b779 100644
--- a/src/core/PortalManager.hpp
+++ b/src/core/PortalManager.hpp
@@ -10,6 +10,7 @@
 #include "../portals/GlobalShortcuts.hpp"
 #include "../helpers/Timer.hpp"
 #include "../shared/ToplevelManager.hpp"
+#include "../shared/ToplevelMappingManager.hpp"
 #include <gbm.h>
 #include <xf86drm.h>
 
@@ -63,7 +64,8 @@ class CPortalManager {
     } m_sPortals;
 
     struct {
-        std::unique_ptr<CToplevelManager> toplevel;
+        std::unique_ptr<CToplevelManager>        toplevel;
+        std::unique_ptr<CToplevelMappingManager> toplevelMapping;
     } m_sHelpers;
 
     struct {
diff --git a/src/shared/ScreencopyShared.cpp b/src/shared/ScreencopyShared.cpp
index 0db7b9c5..c5db2bce 100644
--- a/src/shared/ScreencopyShared.cpp
+++ b/src/shared/ScreencopyShared.cpp
@@ -31,8 +31,9 @@ std::string buildWindowList() {
         return result;
 
     for (auto& e : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
-        result += std::format("{}[HC>]{}[HT>]{}[HE>]", (uint32_t)(((uint64_t)e->handle->resource()) & 0xFFFFFFFF), sanitizeNameForWindowList(e->windowClass),
-                              sanitizeNameForWindowList(e->windowTitle));
+        result += std::format("{}[HC>]{}[HT>]{}[HE>]{}[HA>]", (uint32_t)(((uint64_t)e->handle->resource()) & 0xFFFFFFFF), sanitizeNameForWindowList(e->windowClass),
+                              sanitizeNameForWindowList(e->windowTitle),
+                              g_pPortalManager->m_sHelpers.toplevelMapping ? g_pPortalManager->m_sHelpers.toplevelMapping->getWindowForToplevel(e->handle) : 0);
     }
 
     return result;
diff --git a/src/shared/ToplevelManager.cpp b/src/shared/ToplevelManager.cpp
index c3d072a2..ffc50658 100644
--- a/src/shared/ToplevelManager.cpp
+++ b/src/shared/ToplevelManager.cpp
@@ -19,6 +19,8 @@ SToplevelHandle::SToplevelHandle(SP<CCZwlrForeignToplevelHandleV1> handle_) : ha
         Debug::log(TRACE, "[toplevel] toplevel at {} closed", (void*)this);
 
         std::erase_if(g_pPortalManager->m_sHelpers.toplevel->m_vToplevels, [&](const auto& e) { return e.get() == this; });
+        if (g_pPortalManager->m_sHelpers.toplevelMapping)
+            g_pPortalManager->m_sHelpers.toplevelMapping->m_muAddresses.erase(this->handle);
     });
 }
 
@@ -41,9 +43,15 @@ void CToplevelManager::activate() {
     m_pManager->setToplevel([this](CCZwlrForeignToplevelManagerV1* r, wl_proxy* newHandle) {
         Debug::log(TRACE, "[toplevel] New toplevel at {}", (void*)newHandle);
 
-        m_vToplevels.emplace_back(makeShared<SToplevelHandle>(makeShared<CCZwlrForeignToplevelHandleV1>(newHandle)));
+        const auto HANDLE = m_vToplevels.emplace_back(makeShared<SToplevelHandle>(makeShared<CCZwlrForeignToplevelHandleV1>(newHandle)));
+        if (g_pPortalManager->m_sHelpers.toplevelMapping)
+            g_pPortalManager->m_sHelpers.toplevelMapping->fetchWindowForToplevel(HANDLE->handle);
+    });
+    m_pManager->setFinished([this](CCZwlrForeignToplevelManagerV1* r) {
+        m_vToplevels.clear();
+        if (g_pPortalManager->m_sHelpers.toplevelMapping)
+            g_pPortalManager->m_sHelpers.toplevelMapping->m_muAddresses.clear();
     });
-    m_pManager->setFinished([this](CCZwlrForeignToplevelManagerV1* r) { m_vToplevels.clear(); });
 
     wl_display_roundtrip(g_pPortalManager->m_sWaylandConnection.display);
 
@@ -60,6 +68,8 @@ void CToplevelManager::deactivate() {
 
     m_pManager.reset();
     m_vToplevels.clear();
+    if (g_pPortalManager->m_sHelpers.toplevelMapping)
+        g_pPortalManager->m_sHelpers.toplevelMapping->m_muAddresses.clear();
 
     Debug::log(LOG, "[toplevel] unbound manager");
 }
diff --git a/src/shared/ToplevelMappingManager.cpp b/src/shared/ToplevelMappingManager.cpp
new file mode 100644
index 00000000..9fb93fca
--- /dev/null
+++ b/src/shared/ToplevelMappingManager.cpp
@@ -0,0 +1,39 @@
+#include "ToplevelMappingManager.hpp"
+#include "../helpers/Log.hpp"
+
+CToplevelMappingManager::CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr) : m_pManager(mgr) {
+    Debug::log(LOG, "[toplevel mapping] registered manager");
+}
+
+void CToplevelMappingManager::fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle) {
+    if (!handle)
+        return;
+
+    Debug::log(TRACE, "[toplevel mapping] fetching window for toplevel at {}", (void*)handle.get());
+    auto const HANDLE = makeShared<CCHyprlandToplevelWindowMappingHandleV1>(m_pManager->sendGetWindowForToplevelWlr(handle->resource()));
+
+    m_vHandles.push_back(HANDLE);
+
+    HANDLE->setWindowAddress([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h, uint32_t address_hi, uint32_t address) {
+        const auto ADDRESS = (uint64_t)address_hi << 32 | address;
+        m_muAddresses.insert_or_assign(handle, ADDRESS);
+        Debug::log(TRACE, "[toplevel mapping] mapped toplevel at {} to window {}", (void*)handle.get(), ADDRESS);
+        std::erase_if(m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+
+    HANDLE->setFailed([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h) {
+        Debug::log(TRACE, "[toplevel mapping] failed to map toplevel at {} to window", (void*)handle.get());
+        std::erase_if(m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+}
+
+uint64_t CToplevelMappingManager::getWindowForToplevel(CSharedPointer<CCZwlrForeignToplevelHandleV1> handle) {
+    auto iter = m_muAddresses.find(handle);
+    if (iter != m_muAddresses.end())
+        return iter->second;
+
+    if (handle)
+        Debug::log(TRACE, "[toplevel mapping] did not find window address for toplevel at {}", (void*)handle.get());
+
+    return 0;
+}
diff --git a/src/shared/ToplevelMappingManager.hpp b/src/shared/ToplevelMappingManager.hpp
new file mode 100644
index 00000000..6bbf80f1
--- /dev/null
+++ b/src/shared/ToplevelMappingManager.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "wayland.hpp"
+#include "hyprland-toplevel-mapping-v1.hpp"
+#include "wlr-foreign-toplevel-management-unstable-v1.hpp"
+#include <memory>
+#include "../includes.hpp"
+
+class CToplevelMappingManager {
+  public:
+    CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr);
+
+    uint64_t getWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle);
+
+  private:
+    SP<CCHyprlandToplevelMappingManagerV1>                          m_pManager = nullptr;
+
+    std::unordered_map<SP<CCZwlrForeignToplevelHandleV1>, uint64_t> m_muAddresses;
+    std::vector<SP<CCHyprlandToplevelWindowMappingHandleV1>>        m_vHandles;
+    void                                                            fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle);
+
+    friend struct SToplevelHandle;
+    friend class CToplevelManager;
+};
\ No newline at end of file
diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols
index 4d29e484..3a5c2bda 160000
--- a/subprojects/hyprland-protocols
+++ b/subprojects/hyprland-protocols
@@ -1 +1 @@
-Subproject commit 4d29e48433270a2af06b8bc711ca1fe5109746cd
+Subproject commit 3a5c2bda1c1a4e55cc1330c782547695a93f05b2


Reviews:
user: login: vaxerski
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-06T14:51:52Z
user: login: WhySoBad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-06T16:03:59Z
user: login: WhySoBad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-06T16:05:25Z
user: login: vaxerski
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T18:47:53Z
user: login: WhySoBad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T22:44:17Z
user: login: vaxerski
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T00:14:01Z
user: login: WhySoBad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:30:06Z
user: login: vaxerski
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-25T09:55:02Z

Review comments:
diff_hunk: @@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
path: protocols/ext-foreign-toplevel-list-v1.xml
user: login: vaxerski
body: why is this protocol added when it's in w-p?
created_at: 2025-04-06T14:49:51Z
author_association: MEMBER
diff_hunk: @@ -192,6 +192,11 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
         if (!std::any_cast<Hyprlang::INT>(m_sConfig.config->getConfigValue("general:toplevel_dynamic_bind")))
             m_sHelpers.toplevel->activate();
     }
+
+    else if (INTERFACE == hyprland_toplevel_mapping_manager_v1_interface.name) {
path: src/core/PortalManager.cpp
user: login: vaxerski
body: you don't handle cases in the codebase where this is never called (e.g. hyprland 0.48.1). You need to handle them appropriately, likely send HA> of 0.
created_at: 2025-04-06T14:51:25Z
author_association: MEMBER
diff_hunk: @@ -192,6 +192,11 @@ void CPortalManager::onGlobal(uint32_t name, const char* interface, uint32_t ver
         if (!std::any_cast<Hyprlang::INT>(m_sConfig.config->getConfigValue("general:toplevel_dynamic_bind")))
             m_sHelpers.toplevel->activate();
     }
+
+    else if (INTERFACE == hyprland_toplevel_mapping_manager_v1_interface.name) {
path: src/core/PortalManager.cpp
user: login: WhySoBad
body: done, I added a null check everywhere where the struct member is accessed
created_at: 2025-04-06T16:03:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
path: protocols/ext-foreign-toplevel-list-v1.xml
user: login: WhySoBad
body: good question, I may have thought it's part of wlr but idk

anyways, I've removed it 
created_at: 2025-04-06T16:05:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,40 @@
+#include "ToplevelMappingManager.hpp"
+#include "../helpers/Log.hpp"
+#include "../core/PortalManager.hpp"
+
+CToplevelMappingManager::CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr) : m_pManager(mgr) {
+    Debug::log(LOG, "[toplevel mapping] registered manager");
+}
+
+void CToplevelMappingManager::fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle) {
+    if (!handle)
+        return;
+
+    Debug::log(TRACE, "[toplevel mapping] fetching window for toplevel at {}", (void*)handle.get());
+    auto const HANDLE = makeShared<CCHyprlandToplevelWindowMappingHandleV1>(m_pManager->sendGetWindowForToplevelWlr(handle->resource()));
+
+    m_vHandles.push_back(HANDLE);
+
+    HANDLE->setWindowAddress([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h, uint32_t address_hi, uint32_t address) {
+        const auto ADDRESS = (uint64_t)address_hi << 32 | address;
+        this->m_muAddresses.insert_or_assign(handle, ADDRESS);
+        Debug::log(TRACE, "[toplevel mapping] mapped toplevel at {} to window {}", (void*)handle.get(), ADDRESS);
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+
+    HANDLE->setFailed([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h) {
+        Debug::log(TRACE, "[toplevel mapping] failed to map toplevel at {} to window", (void*)handle.get());
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
path: src/shared/ToplevelMappingManager.cpp
user: login: vaxerski
body: we dont use this->
created_at: 2025-04-24T18:47:47Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,40 @@
+#include "ToplevelMappingManager.hpp"
+#include "../helpers/Log.hpp"
+#include "../core/PortalManager.hpp"
+
+CToplevelMappingManager::CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr) : m_pManager(mgr) {
+    Debug::log(LOG, "[toplevel mapping] registered manager");
+}
+
+void CToplevelMappingManager::fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle) {
+    if (!handle)
+        return;
+
+    Debug::log(TRACE, "[toplevel mapping] fetching window for toplevel at {}", (void*)handle.get());
+    auto const HANDLE = makeShared<CCHyprlandToplevelWindowMappingHandleV1>(m_pManager->sendGetWindowForToplevelWlr(handle->resource()));
+
+    m_vHandles.push_back(HANDLE);
+
+    HANDLE->setWindowAddress([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h, uint32_t address_hi, uint32_t address) {
+        const auto ADDRESS = (uint64_t)address_hi << 32 | address;
+        this->m_muAddresses.insert_or_assign(handle, ADDRESS);
+        Debug::log(TRACE, "[toplevel mapping] mapped toplevel at {} to window {}", (void*)handle.get(), ADDRESS);
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+
+    HANDLE->setFailed([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h) {
+        Debug::log(TRACE, "[toplevel mapping] failed to map toplevel at {} to window", (void*)handle.get());
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
path: src/shared/ToplevelMappingManager.cpp
user: login: WhySoBad
body: replaced it with `g_pPortalManager->m_sHelpers.toplevelMapping`
created_at: 2025-04-24T22:44:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,40 @@
+#include "ToplevelMappingManager.hpp"
+#include "../helpers/Log.hpp"
+#include "../core/PortalManager.hpp"
+
+CToplevelMappingManager::CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr) : m_pManager(mgr) {
+    Debug::log(LOG, "[toplevel mapping] registered manager");
+}
+
+void CToplevelMappingManager::fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle) {
+    if (!handle)
+        return;
+
+    Debug::log(TRACE, "[toplevel mapping] fetching window for toplevel at {}", (void*)handle.get());
+    auto const HANDLE = makeShared<CCHyprlandToplevelWindowMappingHandleV1>(m_pManager->sendGetWindowForToplevelWlr(handle->resource()));
+
+    m_vHandles.push_back(HANDLE);
+
+    HANDLE->setWindowAddress([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h, uint32_t address_hi, uint32_t address) {
+        const auto ADDRESS = (uint64_t)address_hi << 32 | address;
+        this->m_muAddresses.insert_or_assign(handle, ADDRESS);
+        Debug::log(TRACE, "[toplevel mapping] mapped toplevel at {} to window {}", (void*)handle.get(), ADDRESS);
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+
+    HANDLE->setFailed([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h) {
+        Debug::log(TRACE, "[toplevel mapping] failed to map toplevel at {} to window", (void*)handle.get());
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
path: src/shared/ToplevelMappingManager.cpp
user: login: vaxerski
body: you misunderstood. Capturing `this` is completely fine. I was just talking about `this->`. It's implicit, so you can just drop it
created_at: 2025-04-25T00:14:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,40 @@
+#include "ToplevelMappingManager.hpp"
+#include "../helpers/Log.hpp"
+#include "../core/PortalManager.hpp"
+
+CToplevelMappingManager::CToplevelMappingManager(SP<CCHyprlandToplevelMappingManagerV1> mgr) : m_pManager(mgr) {
+    Debug::log(LOG, "[toplevel mapping] registered manager");
+}
+
+void CToplevelMappingManager::fetchWindowForToplevel(SP<CCZwlrForeignToplevelHandleV1> handle) {
+    if (!handle)
+        return;
+
+    Debug::log(TRACE, "[toplevel mapping] fetching window for toplevel at {}", (void*)handle.get());
+    auto const HANDLE = makeShared<CCHyprlandToplevelWindowMappingHandleV1>(m_pManager->sendGetWindowForToplevelWlr(handle->resource()));
+
+    m_vHandles.push_back(HANDLE);
+
+    HANDLE->setWindowAddress([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h, uint32_t address_hi, uint32_t address) {
+        const auto ADDRESS = (uint64_t)address_hi << 32 | address;
+        this->m_muAddresses.insert_or_assign(handle, ADDRESS);
+        Debug::log(TRACE, "[toplevel mapping] mapped toplevel at {} to window {}", (void*)handle.get(), ADDRESS);
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
+    });
+
+    HANDLE->setFailed([this, handle](CCHyprlandToplevelWindowMappingHandleV1* h) {
+        Debug::log(TRACE, "[toplevel mapping] failed to map toplevel at {} to window", (void*)handle.get());
+        std::erase_if(this->m_vHandles, [&](const auto& other) { return other.get() == h; });
path: src/shared/ToplevelMappingManager.cpp
user: login: WhySoBad
body: I see, I've changed it now
created_at: 2025-04-25T09:30:06Z
author_association: CONTRIBUTOR

PR comments:
user: login: WhySoBad
created_at: 2025-04-24T18:08:46Z
body: Hi,

This pull request probably also got lost in your notifications. 
author_association: CONTRIBUTOR
user: login: vaxerski
created_at: 2025-04-24T18:46:44Z
body: ye
author_association: MEMBER
user: login: WhySoBad
created_at: 2025-04-28T20:20:48Z
body: I think can be merged, right?
author_association: CONTRIBUTOR
user: login: vaxerski
created_at: 2025-04-28T20:21:51Z
body: forgor as usual, thanks for reminding me
author_association: MEMBER