summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Miller <2032667+tnymlr@users.noreply.github.com>2026-05-03 06:06:00 +1000
committerGitHub <noreply@github.com>2026-05-02 21:06:00 +0100
commit334b361c8d1bf17652663768fd9237b46287781f (patch)
tree41a24021bf21baf2de138f010a8a8575f5cbef8b
parentf60e50da007aaf55a24d5e25e7a761f3ead51aaa (diff)
screenshare: round captureBox after scaling to fix region capture at fractional scales (#14257)
After scaling m_captureBox from logical to pixel coordinates, the box may have non-integer dimensions (e.g. logical 401x301 at scale 1.25 -> pixel 501.25x376.25). m_bufferSize is then computed as captureBox.size() and sent to the client as int32 width/height (truncating the fraction), but m_bufferSize itself stays as a fractional Vector2D. When the client allocates the integer-sized buffer and submits it, CScreenshareFrame::share() rejects it with ERROR_BUFFER_SIZE because Vector2D::operator== is exact double comparison: (501, 376) != (501.25, 376.25). The frame is sent failed, and the client retries forever. The SHARE_WINDOW path already rounds its bufferSize; the SHARE_REGION path didn't. Round the captureBox immediately after scaling so all downstream consumers (m_bufferSize, render translates) see clean integer pixel coordinates. Reproducer at scale 1.25 on a 1920x1080 monitor: wf-recorder -g '500,200 401x301' -f /tmp/x.mp4 # "Failed to copy frame, retrying..." until exit wf-recorder -g '500,200 400x300' -f /tmp/x.mp4 # works (400*1.25=500, 300*1.25=375, both integer)
-rw-r--r--src/managers/screenshare/ScreenshareSession.cpp5
1 files changed, 3 insertions, 2 deletions
diff --git a/src/managers/screenshare/ScreenshareSession.cpp b/src/managers/screenshare/ScreenshareSession.cpp
index 1f7aeb88..7e6aea6f 100644
--- a/src/managers/screenshare/ScreenshareSession.cpp
+++ b/src/managers/screenshare/ScreenshareSession.cpp
@@ -80,8 +80,9 @@ void CScreenshareSession::init() {
if (g_pEventLoopManager)
g_pEventLoopManager->addTimer(m_shareStopTimer);
- // scale capture box since it's in logical coords
- m_captureBox.scale(monitor()->m_scale);
+ // scale capture box since it's in logical coords; round to integer pixel
+ // dims so m_bufferSize matches the int32 size we send to the client
+ m_captureBox.scale(monitor()->m_scale).round();
m_listeners.monitorDestroyed = monitor()->m_events.disconnect.listen([this]() { stop(); });
m_listeners.monitorModeChanged = monitor()->m_events.modeChanged.listen([this]() {