Skip to content

Commit d313cbd

Browse files
committed
implement image capture source protocol
1 parent 2b07c54 commit d313cbd

File tree

5 files changed

+181
-2
lines changed

5 files changed

+181
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ protocolnew("staging/xdg-system-bell" "xdg-system-bell-v1" false)
384384
protocolnew("staging/ext-workspace" "ext-workspace-v1" false)
385385
protocolnew("staging/ext-data-control" "ext-data-control-v1" false)
386386
protocolnew("staging/pointer-warp" "pointer-warp-v1" false)
387+
protocolnew("staging/ext-image-capture-source" "ext-image-capture-source-v1" false)
387388

388389
protocolwayland()
389390

protocols/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ protocols = [
7878
wayland_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml',
7979
wayland_protocol_dir / 'staging/ext-data-control/ext-data-control-v1.xml',
8080
wayland_protocol_dir / 'staging/pointer-warp/pointer-warp-v1.xml',
81+
wayland_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
8182
]
8283

8384
wl_protocols = []

src/managers/ProtocolManager.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "../protocols/SecurityContext.hpp"
5151
#include "../protocols/CTMControl.hpp"
5252
#include "../protocols/HyprlandSurface.hpp"
53+
#include "../protocols/ImageCaptureSource.hpp"
5354
#include "../protocols/core/Seat.hpp"
5455
#include "../protocols/core/DataDevice.hpp"
5556
#include "../protocols/core/Compositor.hpp"
@@ -195,6 +196,10 @@ CProtocolManager::CProtocolManager() {
195196
PROTO::extDataDevice = makeUnique<CExtDataDeviceProtocol>(&ext_data_control_manager_v1_interface, 1, "ExtDataDevice");
196197
PROTO::pointerWarp = makeUnique<CPointerWarpProtocol>(&wp_pointer_warp_v1_interface, 1, "PointerWarp");
197198

199+
PROTO::imageCaptureSource = makeUnique<CImageCaptureSourceProtocol>();
200+
201+
// ! please read the top of this file before adding another protocol
202+
198203
if (*PENABLECM)
199204
PROTO::colorManagement = makeUnique<CColorManagementProtocol>(&wp_color_manager_v1_interface, 1, "ColorManagement", *PDEBUGCM);
200205

@@ -203,8 +208,6 @@ CProtocolManager::CProtocolManager() {
203208
PROTO::frogColorManagement = makeUnique<CFrogColorManagementProtocol>(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement");
204209
}
205210

206-
// ! please read the top of this file before adding another protocol
207-
208211
for (auto const& b : g_pCompositor->m_aqBackend->getImplementations()) {
209212
if (b->type() != Aquamarine::AQ_BACKEND_DRM)
210213
continue;
@@ -298,6 +301,7 @@ CProtocolManager::~CProtocolManager() {
298301
PROTO::extWorkspace.reset();
299302
PROTO::extDataDevice.reset();
300303
PROTO::pointerWarp.reset();
304+
PROTO::imageCaptureSource.reset();
301305

302306
for (auto& [_, lease] : PROTO::lease) {
303307
lease.reset();
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include "ImageCaptureSource.hpp"
2+
#include "core/Output.hpp"
3+
#include "../helpers/Monitor.hpp"
4+
#include "../desktop/Window.hpp"
5+
#include "ForeignToplevel.hpp"
6+
7+
CImageCaptureSource::CImageCaptureSource(SP<CExtImageCaptureSourceV1> resource, PHLMONITOR pMonitor) : m_resource(resource) {
8+
m_listeners.destroy = m_monitor->m_events.disconnect.registerListener([this](std::any data) { PROTO::imageCaptureSource->destroyResource(this); });
9+
m_resource->setData(this);
10+
}
11+
12+
CImageCaptureSource::CImageCaptureSource(SP<CExtImageCaptureSourceV1> resource, PHLWINDOW pWindow) : m_resource(resource) {
13+
m_listeners.destroy = m_window->m_events.destroy.registerListener([this](std::any data) { PROTO::imageCaptureSource->destroyResource(this); });
14+
m_resource->setData(this);
15+
}
16+
17+
CImageCaptureSource::~CImageCaptureSource() {
18+
m_events.destroy.emit();
19+
}
20+
21+
COutputImageCaptureSourceProtocol::COutputImageCaptureSourceProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
22+
;
23+
}
24+
25+
void COutputImageCaptureSourceProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
26+
const auto RESOURCE = PROTO::imageCaptureSource->m_outputManagers.emplace_back(makeShared<CExtOutputImageCaptureSourceManagerV1>(client, ver, id));
27+
28+
if UNLIKELY (!RESOURCE->resource()) {
29+
wl_client_post_no_memory(client);
30+
PROTO::imageCaptureSource->m_outputManagers.pop_back();
31+
return;
32+
}
33+
34+
RESOURCE->setDestroy([](CExtOutputImageCaptureSourceManagerV1* pMgr) { PROTO::imageCaptureSource->destroyResource(pMgr); });
35+
RESOURCE->setOnDestroy([](CExtOutputImageCaptureSourceManagerV1* pMgr) { PROTO::imageCaptureSource->destroyResource(pMgr); });
36+
RESOURCE->setCreateSource([](CExtOutputImageCaptureSourceManagerV1* pMgr, uint32_t id, wl_resource* output) {
37+
PHLMONITOR pMonitor = CWLOutputResource::fromResource(output)->m_monitor.lock();
38+
if (!pMonitor) {
39+
LOGM(LOG, "Client tried to create source from invalid output resource");
40+
pMgr->error(-1, "invalid output resource");
41+
return;
42+
}
43+
44+
auto PSOURCE =
45+
PROTO::imageCaptureSource->m_sources.emplace_back(makeShared<CImageCaptureSource>(makeShared<CExtImageCaptureSourceV1>(pMgr->client(), pMgr->version(), id), pMonitor));
46+
PSOURCE->m_self = PSOURCE;
47+
48+
LOGM(LOG, "New capture source for monitor: {}", pMonitor->m_name);
49+
});
50+
}
51+
52+
CToplevelImageCaptureSourceProtocol::CToplevelImageCaptureSourceProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
53+
;
54+
}
55+
56+
void CToplevelImageCaptureSourceProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
57+
const auto RESOURCE = PROTO::imageCaptureSource->m_toplevelManagers.emplace_back(makeShared<CExtForeignToplevelImageCaptureSourceManagerV1>(client, ver, id));
58+
59+
if UNLIKELY (!RESOURCE->resource()) {
60+
RESOURCE->noMemory();
61+
PROTO::imageCaptureSource->m_toplevelManagers.pop_back();
62+
return;
63+
}
64+
65+
RESOURCE->setDestroy([](CExtForeignToplevelImageCaptureSourceManagerV1* pMgr) { PROTO::imageCaptureSource->destroyResource(pMgr); });
66+
RESOURCE->setOnDestroy([](CExtForeignToplevelImageCaptureSourceManagerV1* pMgr) { PROTO::imageCaptureSource->destroyResource(pMgr); });
67+
RESOURCE->setCreateSource([](CExtForeignToplevelImageCaptureSourceManagerV1* pMgr, uint32_t id, wl_resource* handle) {
68+
PHLWINDOW pWindow = PROTO::foreignToplevel->windowFromHandleResource(handle);
69+
if (!pWindow) {
70+
LOGM(LOG, "Client tried to create source from invalid foreign toplevel handle resource");
71+
pMgr->error(-1, "invalid foreign toplevel resource");
72+
return;
73+
}
74+
75+
auto PSOURCE =
76+
PROTO::imageCaptureSource->m_sources.emplace_back(makeShared<CImageCaptureSource>(makeShared<CExtImageCaptureSourceV1>(pMgr->client(), pMgr->version(), id), pWindow));
77+
PSOURCE->m_self = PSOURCE;
78+
79+
LOGM(LOG, "New capture source for foreign toplevel: {}", pWindow->m_title);
80+
});
81+
}
82+
83+
CImageCaptureSourceProtocol::CImageCaptureSourceProtocol() {
84+
m_output = makeUnique<COutputImageCaptureSourceProtocol>(&ext_output_image_capture_source_manager_v1_interface, 1, "OutputImageCaptureSource");
85+
m_toplevel = makeUnique<CToplevelImageCaptureSourceProtocol>(&ext_foreign_toplevel_image_capture_source_manager_v1_interface, 1, "ForeignToplevelImageCaptureSource");
86+
}
87+
88+
SP<CImageCaptureSource> CImageCaptureSourceProtocol::sourceFromResource(wl_resource* res) {
89+
auto data = sc<CImageCaptureSource*>(sc<CExtImageCaptureSourceV1*>(wl_resource_get_user_data(res))->data());
90+
return data && data->m_self ? data->m_self.lock() : nullptr;
91+
}
92+
93+
void CImageCaptureSourceProtocol::destroyResource(CExtOutputImageCaptureSourceManagerV1* resource) {
94+
std::erase_if(m_outputManagers, [&](const auto& other) { return other.get() == resource; });
95+
}
96+
void CImageCaptureSourceProtocol::destroyResource(CExtForeignToplevelImageCaptureSourceManagerV1* resource) {
97+
std::erase_if(m_toplevelManagers, [&](const auto& other) { return other.get() == resource; });
98+
}
99+
void CImageCaptureSourceProtocol::destroyResource(CImageCaptureSource* resource) {
100+
std::erase_if(m_sources, [&](const auto& other) { return other.get() == resource; });
101+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
3+
#include <vector>
4+
5+
#include "../defines.hpp"
6+
#include "../helpers/signal/Signal.hpp"
7+
#include "WaylandProtocol.hpp"
8+
#include "ext-image-capture-source-v1.hpp"
9+
10+
class CImageCaptureSource {
11+
public:
12+
CImageCaptureSource(SP<CExtImageCaptureSourceV1> resource, PHLMONITOR pMonitor);
13+
CImageCaptureSource(SP<CExtImageCaptureSourceV1> resource, PHLWINDOW pWindow);
14+
~CImageCaptureSource();
15+
16+
struct {
17+
CSignalT<> destroy;
18+
} m_events;
19+
20+
WP<CImageCaptureSource> m_self;
21+
22+
private:
23+
SP<CExtImageCaptureSourceV1> m_resource;
24+
25+
struct {
26+
CHyprSignalListener destroy;
27+
} m_listeners;
28+
29+
PHLMONITOR m_monitor;
30+
PHLWINDOW m_window;
31+
};
32+
33+
class COutputImageCaptureSourceProtocol : public IWaylandProtocol {
34+
public:
35+
COutputImageCaptureSourceProtocol(const wl_interface* iface, const int& ver, const std::string& name);
36+
37+
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
38+
};
39+
40+
class CToplevelImageCaptureSourceProtocol : public IWaylandProtocol {
41+
public:
42+
CToplevelImageCaptureSourceProtocol(const wl_interface* iface, const int& ver, const std::string& name);
43+
44+
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
45+
};
46+
47+
class CImageCaptureSourceProtocol {
48+
public:
49+
CImageCaptureSourceProtocol();
50+
51+
SP<CImageCaptureSource> sourceFromResource(wl_resource* resource);
52+
53+
void destroyResource(CExtOutputImageCaptureSourceManagerV1* resource);
54+
void destroyResource(CExtForeignToplevelImageCaptureSourceManagerV1* resource);
55+
void destroyResource(CImageCaptureSource* resource);
56+
57+
private:
58+
UP<COutputImageCaptureSourceProtocol> m_output;
59+
UP<CToplevelImageCaptureSourceProtocol> m_toplevel;
60+
61+
std::vector<SP<CExtOutputImageCaptureSourceManagerV1>> m_outputManagers;
62+
std::vector<SP<CExtForeignToplevelImageCaptureSourceManagerV1>> m_toplevelManagers;
63+
64+
std::vector<SP<CImageCaptureSource>> m_sources;
65+
66+
friend class COutputImageCaptureSourceProtocol;
67+
friend class CToplevelImageCaptureSourceProtocol;
68+
};
69+
70+
namespace PROTO {
71+
inline UP<CImageCaptureSourceProtocol> imageCaptureSource;
72+
};

0 commit comments

Comments
 (0)