11using System ;
22using System . Collections . Generic ;
3+ using System . Linq ;
34using System . Threading . Tasks ;
5+ using PuppeteerSharp . Helpers ;
46using PuppeteerSharp . Media ;
57using PuppeteerSharp . Messaging ;
68
79namespace PuppeteerSharp
810{
911 internal class EmulationManager
1012 {
13+ private readonly ConcurrentSet < CDPSession > _secondaryClients = [ ] ;
1114 private CDPSession _client ;
1215 private bool _emulatingMobile ;
1316 private bool _hasTouch ;
17+ private ViewPortOptions _viewport ;
1418
1519 public EmulationManager ( CDPSession client )
1620 {
@@ -19,7 +23,18 @@ public EmulationManager(CDPSession client)
1923
2024 public bool JavascriptEnabled { get ; private set ; } = true ;
2125
22- internal void UpdateClient ( CDPSession client ) => _client = client ;
26+ internal void UpdateClient ( CDPSession client )
27+ {
28+ _client = client ;
29+ _secondaryClients . Remove ( client ) ;
30+ }
31+
32+ internal async Task RegisterSecondaryPageAsync ( CDPSession client )
33+ {
34+ _secondaryClients . Add ( client ) ;
35+ await ApplyViewportAsync ( client ) . ConfigureAwait ( false ) ;
36+ client . Disconnected += ( sender , e ) => _secondaryClients . Remove ( client ) ;
37+ }
2338
2439 internal async Task EmulateTimezoneAsync ( string timezoneId )
2540 {
@@ -72,33 +87,22 @@ await _client.SendAsync(
7287
7388 internal async Task < bool > EmulateViewportAsync ( ViewPortOptions viewport )
7489 {
75- var mobile = viewport . IsMobile ;
76- var width = viewport . Width ;
77- var height = viewport . Height ;
78- var deviceScaleFactor = viewport . DeviceScaleFactor ;
79- var screenOrientation = viewport . IsLandscape
80- ? new ScreenOrientation { Angle = 90 , Type = ScreenOrientationType . LandscapePrimary , }
81- : new ScreenOrientation { Angle = 0 , Type = ScreenOrientationType . PortraitPrimary , } ;
82- var hasTouch = viewport . HasTouch ;
90+ _viewport = viewport ;
8391
84- await Task . WhenAll (
85- [
86- _client . SendAsync ( "Emulation.setDeviceMetricsOverride" , new EmulationSetDeviceMetricsOverrideRequest
87- {
88- Mobile = mobile ,
89- Width = width ,
90- Height = height ,
91- DeviceScaleFactor = deviceScaleFactor ,
92- ScreenOrientation = screenOrientation ,
93- } ) ,
94- _client . SendAsync (
95- "Emulation.setTouchEmulationEnabled" ,
96- new EmulationSetTouchEmulationEnabledRequest { Enabled = hasTouch , } ) ,
97- ] ) . ConfigureAwait ( false ) ;
92+ await ApplyViewportAsync ( _client ) . ConfigureAwait ( false ) ;
9893
94+ var mobile = viewport . IsMobile ;
95+ var hasTouch = viewport . HasTouch ;
9996 var reloadNeeded = _emulatingMobile != mobile || _hasTouch != hasTouch ;
10097 _emulatingMobile = mobile ;
10198 _hasTouch = hasTouch ;
99+
100+ if ( ! reloadNeeded )
101+ {
102+ // If the page will be reloaded, no need to adjust secondary clients.
103+ await Task . WhenAll ( _secondaryClients . Select ( ApplyViewportAsync ) ) . ConfigureAwait ( false ) ;
104+ }
105+
102106 return reloadNeeded ;
103107 }
104108
@@ -165,5 +169,38 @@ internal Task SetJavaScriptEnabledAsync(bool enabled)
165169 Value = ! enabled ,
166170 } ) ;
167171 }
172+
173+ private async Task ApplyViewportAsync ( CDPSession client )
174+ {
175+ var viewport = _viewport ;
176+ if ( viewport == null )
177+ {
178+ return ;
179+ }
180+
181+ var mobile = viewport . IsMobile ;
182+ var width = viewport . Width ;
183+ var height = viewport . Height ;
184+ var deviceScaleFactor = viewport . DeviceScaleFactor ;
185+ var screenOrientation = viewport . IsLandscape
186+ ? new ScreenOrientation { Angle = 90 , Type = ScreenOrientationType . LandscapePrimary , }
187+ : new ScreenOrientation { Angle = 0 , Type = ScreenOrientationType . PortraitPrimary , } ;
188+ var hasTouch = viewport . HasTouch ;
189+
190+ await Task . WhenAll (
191+ [
192+ client . SendAsync ( "Emulation.setDeviceMetricsOverride" , new EmulationSetDeviceMetricsOverrideRequest
193+ {
194+ Mobile = mobile ,
195+ Width = width ,
196+ Height = height ,
197+ DeviceScaleFactor = deviceScaleFactor ,
198+ ScreenOrientation = screenOrientation ,
199+ } ) ,
200+ client . SendAsync (
201+ "Emulation.setTouchEmulationEnabled" ,
202+ new EmulationSetTouchEmulationEnabledRequest { Enabled = hasTouch , } ) ,
203+ ] ) . ConfigureAwait ( false ) ;
204+ }
168205 }
169206}
0 commit comments