@@ -11,7 +11,7 @@ use tokio::sync::mpsc;
1111use tracing:: debug;
1212
1313use super :: cdp:: CdpEvent ;
14- use super :: session:: { FRAME_GAP , Hooks , MAX_TABS , PageInfo , Session , Tab } ;
14+ use super :: session:: { FRAME_GAP , Hooks , MAX_TABS , PageInfo , QUICK_GAP , Session , Tab } ;
1515use super :: titles:: retitles;
1616
1717impl Session {
@@ -196,29 +196,60 @@ impl Session {
196196 }
197197
198198 fn frame ( & self , session : & str , params : & Value , hooks : & Hooks ) {
199- let ( active, viewport) = {
199+ let ( active, viewport, gap ) = {
200200 let tabs = self . lock ( ) ;
201201 let active = tabs. active ( ) . is_some_and ( |tab| tab. session == session) ;
202- ( active, tabs. viewport )
202+ let gap = if tabs. quick { QUICK_GAP } else { FRAME_GAP } ;
203+ ( active, tabs. viewport , gap)
203204 } ;
204- if active && let Some ( data) = params[ "data" ] . as_str ( ) {
205- let size = |key : & str , fallback : u32 | {
206- params[ "metadata" ] [ key]
207- . as_f64 ( )
208- . map_or ( fallback, |value| value. round ( ) as u32 )
209- } ;
205+ let size = |key : & str , fallback : u32 | {
206+ params[ "metadata" ] [ key]
207+ . as_f64 ( )
208+ . map_or ( fallback, |value| value. round ( ) as u32 )
209+ } ;
210+ let ( width, height) = (
211+ size ( "deviceWidth" , viewport. width ) ,
212+ size ( "deviceHeight" , viewport. height ) ,
213+ ) ;
214+ // The screencast draws in the page's own pixels, however sharp the
215+ // page is (spec 19): on a sharper screen its frame only says the page
216+ // changed, and the frame sent is a screenshot, which is that sharp.
217+ let sharp = active && viewport. scale > 100 ;
218+ if active
219+ && !sharp
220+ && let Some ( data) = params[ "data" ] . as_str ( )
221+ {
210222 hooks. frames . send_replace ( Some ( Arc :: new ( BrowserFrame {
211223 bot_id : hooks. bot . clone ( ) ,
212224 data : data. to_owned ( ) ,
213- width : size ( "deviceWidth" , viewport . width ) ,
214- height : size ( "deviceHeight" , viewport . height ) ,
225+ width,
226+ height,
215227 } ) ) ) ;
216228 }
217229 let cdp = self . cdp . clone ( ) ;
218230 let session = session. to_owned ( ) ;
219231 let ack = json ! ( { "sessionId" : params[ "sessionId" ] } ) ;
232+ let ( frames, bot) = ( hooks. frames . clone ( ) , hooks. bot . clone ( ) ) ;
220233 tokio:: spawn ( async move {
221- tokio:: time:: sleep ( FRAME_GAP ) . await ;
234+ if sharp {
235+ let shot = json ! ( { "format" : "jpeg" , "quality" : 60 , "optimizeForSpeed" : true } ) ;
236+ let taken = cdp
237+ . call ( Some ( & session) , "Page.captureScreenshot" , shot)
238+ . await ;
239+ if let Some ( data) = taken
240+ . ok ( )
241+ . and_then ( |shot| shot[ "data" ] . as_str ( ) . map ( str:: to_owned) )
242+ {
243+ frames. send_replace ( Some ( Arc :: new ( BrowserFrame {
244+ bot_id : bot,
245+ data,
246+ width,
247+ height,
248+ } ) ) ) ;
249+ }
250+ }
251+ // Confirmed only after, so screenshots never pile up.
252+ tokio:: time:: sleep ( gap) . await ;
222253 cdp. send ( Some ( & session) , "Page.screencastFrameAck" , ack) ;
223254 } ) ;
224255 }
0 commit comments