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
69CScreenshareManager::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
1015void 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