diff --git a/lib/features/desktop/desktop_client.dart b/lib/features/desktop/desktop_client.dart index 3ae097e5..de760059 100644 --- a/lib/features/desktop/desktop_client.dart +++ b/lib/features/desktop/desktop_client.dart @@ -111,14 +111,21 @@ class DesktopClient { } }; - // Add transceiver for receiving video (required for unified-plan) + // Add transceivers for receiving video and audio + await _peerConnection!.addTransceiver( + kind: RTCRtpMediaType.RTCRtpMediaTypeAudio, + init: RTCRtpTransceiverInit(direction: TransceiverDirection.RecvOnly), + ); await _peerConnection!.addTransceiver( kind: RTCRtpMediaType.RTCRtpMediaTypeVideo, init: RTCRtpTransceiverInit(direction: TransceiverDirection.RecvOnly), ); // Create SDP Offer - final offer = await _peerConnection!.createOffer({}); + final offer = await _peerConnection!.createOffer({ + 'offerToReceiveAudio': 1, + 'offerToReceiveVideo': 1, + }); await _peerConnection!.setLocalDescription(offer); // Send SDP Offer to Bridge diff --git a/lib/features/desktop/desktop_input_handler.dart b/lib/features/desktop/desktop_input_handler.dart index c5f3f6f6..b2575717 100644 --- a/lib/features/desktop/desktop_input_handler.dart +++ b/lib/features/desktop/desktop_input_handler.dart @@ -162,10 +162,34 @@ Offset? desktopContentPosition( }) { if (viewportSize.width <= 0 || viewportSize.height <= 0) return null; - // We are using FittedBox(fit: BoxFit.fill) which stretches the video - // to fill the viewport exactly, without any padding/offsets. + if (contentSize == null || contentSize.width <= 0 || contentSize.height <= 0) { + return Offset( + (localPosition.dx / viewportSize.width).clamp(0.0, 1.0), + (localPosition.dy / viewportSize.height).clamp(0.0, 1.0), + ); + } + + final double viewportRatio = viewportSize.width / viewportSize.height; + final double contentRatio = contentSize.width / contentSize.height; + + double renderedWidth; + double renderedHeight; + + if (viewportRatio > contentRatio) { + // Viewport is wider, so height is the constraint + renderedHeight = viewportSize.height; + renderedWidth = renderedHeight * contentRatio; + } else { + // Viewport is taller, so width is the constraint + renderedWidth = viewportSize.width; + renderedHeight = renderedWidth / contentRatio; + } + + final double dxOffset = (viewportSize.width - renderedWidth) / 2; + final double dyOffset = (viewportSize.height - renderedHeight) / 2; + return Offset( - (localPosition.dx / viewportSize.width).clamp(0.0, 1.0), - (localPosition.dy / viewportSize.height).clamp(0.0, 1.0), + ((localPosition.dx - dxOffset) / renderedWidth).clamp(0.0, 1.0), + ((localPosition.dy - dyOffset) / renderedHeight).clamp(0.0, 1.0), ); } diff --git a/lib/features/desktop/desktop_view.dart b/lib/features/desktop/desktop_view.dart index d03adb7e..c3af83d9 100644 --- a/lib/features/desktop/desktop_view.dart +++ b/lib/features/desktop/desktop_view.dart @@ -102,6 +102,11 @@ class _DesktopViewState extends State { Future _initRenderer() async { await _localRenderer.initialize(); + _localRenderer.onResize = () { + if (mounted) { + setState(() {}); + } + }; } @override