diff --git a/apps/desktop/src/context/CallContext.tsx b/apps/desktop/src/context/CallContext.tsx index a316843..7773771 100644 --- a/apps/desktop/src/context/CallContext.tsx +++ b/apps/desktop/src/context/CallContext.tsx @@ -1442,20 +1442,29 @@ export function CallProvider({ children }: { children: ReactNode }) { // the same system audio twice and Chromium's version would // include our own renderer playback. audio: preferNativeLoopback ? false : wantAudio, + // Preset dims are passed as `ideal` constraints (not fixed width/height) + // so Chromium picks the closest match preserving the source's aspect + // ratio instead of CROPPING non-matching monitors. Without this, a 16:10 + // monitor (1920×1200, 2560×1600) streamed under a 16:9 preset loses its + // bottom strip — including the Windows taskbar. + // + // LiveKit's VideoResolution types declare width/height as `number`, but + // Chromium's getDisplayMedia accepts the full MediaTrackConstraints shape + // including { ideal: N } objects — we cast through `unknown` to satisfy tsc. ...(ssParams.dims ? { resolution: { - width: ssParams.dims.width, - height: ssParams.dims.height, + width: { ideal: ssParams.dims.width }, + height: { ideal: ssParams.dims.height }, frameRate: fps, - }, + } as unknown as { width: number; height: number; frameRate: number }, } : { resolution: { - width: 3840, - height: 2160, frameRate: fps, - }, + width: undefined, + height: undefined, + } as unknown as { width: number; height: number; frameRate: number }, }), ...(displaySurface ? ({ displaySurface } as { displaySurface: DisplaySurfaceHint })