Skip to content

Commit 77ba086

Browse files
committed
try move screencopy and toplevel export to screenshare manager
1 parent 609eb55 commit 77ba086

File tree

13 files changed

+474
-1012
lines changed

13 files changed

+474
-1012
lines changed

src/events/Windows.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "../desktop/LayerSurface.hpp"
2323
#include "../managers/LayoutManager.hpp"
2424
#include "../managers/EventManager.hpp"
25+
#include "../managers/HookSystemManager.hpp"
2526
#include "../managers/animation/AnimationManager.hpp"
2627

2728
#include <hyprutils/string/String.hpp>

src/helpers/Monitor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "../managers/animation/AnimationManager.hpp"
2828
#include "../managers/animation/DesktopAnimationManager.hpp"
2929
#include "../managers/input/InputManager.hpp"
30+
#include "../managers/HookSystemManager.hpp"
3031
#include "../hyprerror/HyprError.hpp"
3132
#include "sync/SyncTimeline.hpp"
3233
#include "time/Time.hpp"

src/managers/ProtocolManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "../protocols/ExtWorkspace.hpp"
6868
#include "../protocols/ExtDataDevice.hpp"
6969
#include "../protocols/PointerWarp.hpp"
70+
#include "HookSystemManager.hpp"
7071

7172
#include "../helpers/Monitor.hpp"
7273
#include "../render/Renderer.hpp"

src/managers/screenshare/ScreenshareFrame.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010
#include "../../helpers/Monitor.hpp"
1111
#include "../../desktop/Window.hpp"
1212

13-
CScreenshareFrame::CScreenshareFrame(WP<CScreenshareSession> session, SP<IHLBuffer> buffer, FScreenshareCallback callback) :
14-
m_session(session), m_callback(callback), m_buffer(buffer) {
15-
;
13+
CScreenshareFrame::CScreenshareFrame(WP<CScreenshareSession> session, SP<IHLBuffer> buffer, bool overlayCursor, FScreenshareCallback callback) :
14+
m_session(session), m_buffer(buffer), m_overlayCursor(overlayCursor) {
15+
m_callback = callback;
16+
// m_callback = [callback, session](eScreenshareResult result) {
17+
// if (!session.expired() && callback)
18+
// callback(result);
19+
// };
1620
}
1721

1822
CScreenshareFrame::~CScreenshareFrame() {
@@ -24,7 +28,10 @@ bool CScreenshareFrame::done() const {
2428
if (m_session.expired() || m_session->m_stopped)
2529
return true;
2630

27-
if (m_shared || !m_buffer)
31+
if (m_shared)
32+
return true;
33+
34+
if (!m_buffer || !m_buffer->m_resource || !m_buffer->m_resource->good())
2835
return true;
2936

3037
if (m_session->m_type == SHARE_MONITOR && m_session->m_monitor.expired())
@@ -33,7 +40,7 @@ bool CScreenshareFrame::done() const {
3340
if (m_session->m_type == SHARE_REGION && m_session->m_monitor.expired())
3441
return true;
3542

36-
if (m_session->m_type == SHARE_WINDOW && (m_session->m_monitor.expired() || m_session->m_window.expired() || m_session->m_window->m_monitor.expired()))
43+
if (m_session->m_type == SHARE_WINDOW && (m_session->m_monitor.expired() || !validMapped(m_session->m_window)))
3744
return true;
3845

3946
return false;
@@ -59,7 +66,7 @@ void CScreenshareFrame::share() {
5966
}
6067

6168
void CScreenshareFrame::renderMonitor() {
62-
if (m_session->m_type != SHARE_MONITOR || done())
69+
if ((m_session->m_type != SHARE_MONITOR && m_session->m_type != SHARE_REGION) || done())
6370
return;
6471

6572
const auto PMONITOR = m_session->m_monitor.lock();
@@ -137,7 +144,7 @@ void CScreenshareFrame::renderMonitor() {
137144
nullptr);
138145
}
139146

140-
if (m_session->m_overlayCursor) {
147+
if (m_overlayCursor) {
141148
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
142149
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR, Time::steadyNow(), fakeDamage,
143150
g_pInputManager->getMouseCoordsInternal() - PMONITOR->m_position - m_session->m_box.pos() / PMONITOR->m_scale, true);
@@ -157,10 +164,21 @@ void CScreenshareFrame::renderWindow() {
157164
g_pHyprRenderer->renderWindow(PWINDOW, PMONITOR, NOW, false, RENDER_PASS_ALL, true, true);
158165
g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
159166

160-
if (m_session->m_overlayCursor) {
161-
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
162-
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->m_self.lock(), NOW, fakeDamage, g_pInputManager->getMouseCoordsInternal() - PWINDOW->m_realPosition->value());
163-
}
167+
if (!m_overlayCursor)
168+
return;
169+
170+
auto pointerSurfaceResource = g_pSeatManager->m_state.pointerFocus.lock();
171+
172+
if (!pointerSurfaceResource)
173+
return;
174+
175+
auto pointerSurface = CWLSurface::fromResource(pointerSurfaceResource);
176+
177+
if (!pointerSurface || pointerSurface->getWindow() != m_session->m_window)
178+
return;
179+
180+
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
181+
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->m_self.lock(), NOW, fakeDamage, g_pInputManager->getMouseCoordsInternal() - PWINDOW->m_realPosition->value());
164182
}
165183

166184
void CScreenshareFrame::render() {
@@ -186,13 +204,16 @@ void CScreenshareFrame::render() {
186204
}
187205

188206
switch (m_session->m_type) {
207+
case SHARE_REGION: // TODO: could this be better? this is how screencopy works
189208
case SHARE_MONITOR: renderMonitor(); break;
190209
case SHARE_WINDOW: renderWindow(); break;
191-
case SHARE_REGION: break; // TODO
192210
}
193211
}
194212

195213
bool CScreenshareFrame::copyDmabuf() {
214+
if (done())
215+
return false;
216+
196217
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
197218

198219
if (!g_pHyprRenderer->beginRender(m_session->m_monitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, m_buffer, nullptr, true)) {
@@ -213,6 +234,9 @@ bool CScreenshareFrame::copyDmabuf() {
213234
}
214235

215236
bool CScreenshareFrame::copyShm() {
237+
if (done())
238+
return false;
239+
216240
g_pHyprRenderer->makeEGLCurrent();
217241

218242
auto shm = m_buffer->shm();
@@ -286,9 +310,9 @@ void CScreenshareFrame::storeTempFB() {
286310
}
287311

288312
switch (m_session->m_type) {
313+
case SHARE_REGION: // TODO: could this be better? this is how screencopy works
289314
case SHARE_MONITOR: renderMonitor(); break;
290315
case SHARE_WINDOW: renderWindow(); break;
291-
case SHARE_REGION: break; // TODO
292316
}
293317

294318
g_pHyprRenderer->endRender();

src/managers/screenshare/ScreenshareManager.cpp

Lines changed: 129 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
#include "../../render/Renderer.hpp"
33
#include "../../Compositor.hpp"
44
#include "../../desktop/Window.hpp"
5+
#include "../HookSystemManager.hpp"
6+
#include "../EventManager.hpp"
7+
#include "../eventLoop/EventLoopManager.hpp"
58

69
CScreenshareManager::CScreenshareManager() {
7-
;
10+
m_tickTimer = makeShared<CEventLoopTimer>(std::chrono::microseconds(500), [this](SP<CEventLoopTimer> self, void* data) { onTick(); }, nullptr);
11+
if (g_pEventLoopManager) // null in --verify-config mode
12+
g_pEventLoopManager->addTimer(m_tickTimer);
813
}
914

1015
void CScreenshareManager::onOutputCommit(PHLMONITOR monitor) {
@@ -13,54 +18,167 @@ void CScreenshareManager::onOutputCommit(PHLMONITOR monitor) {
1318
return; // nothing to share
1419
}
1520

16-
std::ranges::remove_if(m_sessions, [&](const WP<CScreenshareSession>& session) { return session.expired(); });
21+
LOGM(LOG, "1 onOutputCommit for {}, s {}, ms {}, f {}", monitor->m_name, m_sessions.size(), m_managedSessions.size(), m_frames.size());
22+
23+
std::erase_if(m_sessions, [&](const WP<CScreenshareSession>& session) { return session.expired(); });
24+
25+
LOGM(LOG, "2 onOutputCommit for {}, s {}, ms {}, f {}", monitor->m_name, m_sessions.size(), m_managedSessions.size(), m_frames.size());
1726

1827
std::ranges::for_each(m_frames, [&](UP<CScreenshareFrame>& frame) {
19-
if (!frame->done())
20-
frame->share();
28+
if (!frame || frame->done())
29+
return;
30+
31+
if (frame->m_session->m_monitor != monitor)
32+
return;
33+
34+
if (frame->m_session->m_type == SHARE_WINDOW) {
35+
CBox geometry = {frame->m_session->m_window->m_realPosition->value(), frame->m_session->m_window->m_realSize->value()};
36+
if (geometry.intersection({monitor->m_position, monitor->m_size}).empty())
37+
return;
38+
}
39+
40+
frame->share();
41+
frame->m_session->m_lastFrame.reset();
42+
frame->m_session->m_frameCounter++;
2143
});
2244

23-
std::ranges::remove_if(m_frames, [&](const UP<CScreenshareFrame>& frame) { return frame->done(); });
45+
std::erase_if(m_frames, [&](const UP<CScreenshareFrame>& frame) { return !frame || frame->done(); });
46+
47+
LOGM(LOG, "3 onOutputCommit for {}, s {}, ms {}, f {}", monitor->m_name, m_sessions.size(), m_managedSessions.size(), m_frames.size());
2448
}
2549

26-
UP<CScreenshareSession> CScreenshareManager::newSession(PHLMONITOR monitor, wl_client* client, bool overlayCursor) {
50+
void CScreenshareManager::onTick() {
51+
m_tickTimer->updateTimeout(std::chrono::microseconds(500));
52+
53+
std::ranges::for_each(m_managedSessions, [this](auto& session) {
54+
if (session->m_lastMeasure.getMillis() < 500)
55+
return;
56+
57+
session->m_framesInLastHalfSecond = session->m_session->m_frameCounter;
58+
session->m_session->m_frameCounter = 0;
59+
session->m_lastMeasure.reset();
60+
61+
const auto LASTFRAMEDELTA = session->m_session->m_lastFrame.getMillis() / 1000.0;
62+
const bool FRAMEAWAITING = std::ranges::any_of(m_frames, [&](const auto& frame) { return frame->m_session->m_client == session->m_session->m_client; });
63+
64+
if (session->m_framesInLastHalfSecond > 3 && !session->m_sentScreencast) {
65+
screenshareStarted(session->m_session);
66+
session->m_sentScreencast = true;
67+
} else if (session->m_framesInLastHalfSecond < 4 && LASTFRAMEDELTA > 1.0 && !FRAMEAWAITING) {
68+
session->m_session->stop();
69+
session->m_sentScreencast = false;
70+
}
71+
});
72+
}
73+
74+
void CScreenshareManager::screenshareStarted(WP<CScreenshareSession> session) {
75+
EMIT_HOOK_EVENT("screencastv2", (std::vector<std::any>{1, session->m_type, session->m_name}));
76+
g_pEventManager->postEvent(SHyprIPCEvent{.event = "screencastv2", .data = std::format("1,{},{}", session->m_type, session->m_name)});
77+
LOGM(LOG, "New screenshare session for ({}): {}", session->m_type, session->m_name);
78+
}
79+
80+
UP<CScreenshareSession> CScreenshareManager::newSession(PHLMONITOR monitor, wl_client* client) {
2781
if UNLIKELY (!monitor || !g_pCompositor->monitorExists(monitor)) {
2882
LOGM(ERR, "Client requested sharing of a monitor that is gone");
2983
return nullptr;
3084
}
3185

32-
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(monitor, client, overlayCursor));
86+
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(monitor, client));
3387

3488
session->m_self = session;
3589
m_sessions.emplace_back(session);
3690

91+
screenshareStarted(session);
92+
3793
return session;
3894
}
3995

40-
UP<CScreenshareSession> CScreenshareManager::newSession(PHLMONITOR monitor, CBox captureRegion, wl_client* client, bool overlayCursor) {
96+
UP<CScreenshareSession> CScreenshareManager::newSession(PHLMONITOR monitor, CBox captureRegion, wl_client* client) {
4197
if UNLIKELY (!monitor || !g_pCompositor->monitorExists(monitor)) {
4298
LOGM(ERR, "Client requested sharing of a monitor that is gone");
4399
return nullptr;
44100
}
45101

46-
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(monitor, captureRegion, client, overlayCursor));
102+
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(monitor, captureRegion, client));
47103

48104
session->m_self = session;
49105
m_sessions.emplace_back(session);
50106

107+
screenshareStarted(session);
108+
51109
return session;
52110
}
53111

54-
UP<CScreenshareSession> CScreenshareManager::newSession(PHLWINDOW window, wl_client* client, bool overlayCursor) {
112+
UP<CScreenshareSession> CScreenshareManager::newSession(PHLWINDOW window, wl_client* client) {
55113
if UNLIKELY (!window || !window->m_isMapped) {
56114
LOGM(ERR, "Client requested sharing of window that is gone or not shareable!");
57115
return nullptr;
58116
}
59117

60-
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(window, client, overlayCursor));
118+
UP<CScreenshareSession> session = UP<CScreenshareSession>(new CScreenshareSession(window, client));
61119

62120
session->m_self = session;
63121
m_sessions.emplace_back(session);
64122

123+
screenshareStarted(session);
124+
65125
return session;
66126
}
127+
128+
WP<CScreenshareSession> CScreenshareManager::getManagedSession(wl_client* client, PHLMONITOR monitor) {
129+
return getManagedSession(SHARE_MONITOR, client, monitor, nullptr, {});
130+
}
131+
132+
WP<CScreenshareSession> CScreenshareManager::getManagedSession(wl_client* client, PHLMONITOR monitor, CBox captureBox) {
133+
134+
return getManagedSession(SHARE_REGION, client, monitor, nullptr, captureBox);
135+
}
136+
137+
WP<CScreenshareSession> CScreenshareManager::getManagedSession(wl_client* client, PHLWINDOW window) {
138+
return getManagedSession(SHARE_WINDOW, client, nullptr, window, {});
139+
}
140+
141+
WP<CScreenshareSession> CScreenshareManager::getManagedSession(eScreenshareType type, wl_client* client, PHLMONITOR monitor, PHLWINDOW window, CBox captureBox) {
142+
auto it = std::ranges::find_if(m_managedSessions, [&](const auto& session) {
143+
if (session->m_session->m_client != client || session->m_session->m_type != type)
144+
return false;
145+
146+
switch (type) {
147+
case SHARE_MONITOR: return session->m_session->m_monitor == monitor;
148+
case SHARE_WINDOW: return session->m_session->m_window == window;
149+
case SHARE_REGION: return session->m_session->m_monitor == monitor && session->m_session->m_captureBox == captureBox;
150+
}
151+
152+
return false;
153+
});
154+
155+
if (it == m_managedSessions.end()) {
156+
UP<CScreenshareSession> session;
157+
switch (type) {
158+
case SHARE_MONITOR: session = UP<CScreenshareSession>(new CScreenshareSession(monitor, client)); break;
159+
case SHARE_WINDOW: session = UP<CScreenshareSession>(new CScreenshareSession(window, client)); break;
160+
case SHARE_REGION: session = UP<CScreenshareSession>(new CScreenshareSession(monitor, captureBox, client)); break;
161+
}
162+
163+
session->m_self = session;
164+
m_sessions.emplace_back(session);
165+
166+
it = m_managedSessions.emplace(m_managedSessions.end(), makeUnique<SManagedSession>(std::move(session)));
167+
}
168+
169+
auto& session = *it;
170+
171+
session->stoppedListener = session->m_session->m_events.stopped.listen(
172+
[&]() { std::erase_if(m_managedSessions, [&](const auto& s) { return !s || !session || s->m_session == session->m_session; }); });
173+
174+
return session->m_session;
175+
}
176+
177+
void CScreenshareManager::destroyClientSessions(wl_client* client) {
178+
LOGM(LOG, "destroy client sessions for {:x}", (uintptr_t)client);
179+
std::erase_if(m_managedSessions, [&](const auto& session) { return !session || session->m_session->m_client == client; });
180+
}
181+
182+
CScreenshareManager::SManagedSession::SManagedSession(UP<CScreenshareSession> session) : m_session(std::move(session)) {
183+
m_lastMeasure.reset();
184+
}

0 commit comments

Comments
 (0)