diff options
Diffstat (limited to 'src/server/headless.rs')
| -rw-r--r-- | src/server/headless.rs | 88 |
1 files changed, 68 insertions, 20 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs index 0f9f3bb6..edd1a388 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -2795,7 +2795,7 @@ impl HeadlessServer { return false; }; let prepare_started = crate::render_prof::timer(); - let Some(prepared) = client.render_state.prepare_frame(&frame) else { + let Some(prepared) = client.render_state.prepare_frame(frame) else { client.render_pending = false; crate::render_prof::event("retained_send.skip_identical"); crate::render_prof::duration_since("retained_send.prepare_frame", prepare_started); @@ -2831,7 +2831,7 @@ impl HeadlessServer { match writer.render.try_send(serialized) { Ok(()) => { client.render_pending = false; - client.render_state.commit_sent_frame(frame, prepared); + client.render_state.commit_sent_frame(prepared); crate::render_prof::event("retained_send.sent"); crate::render_prof::duration_since("retained_send.try_send", send_started); true @@ -3007,21 +3007,21 @@ impl HeadlessServer { commit_graphics_cache = false; } + let max_frame_size = if frame.graphics.is_empty() { + MAX_FRAME_SIZE + } else { + MAX_GRAPHICS_FRAME_SIZE + }; + let has_graphics = !frame.graphics.is_empty(); let prepare_started = crate::render_prof::timer(); - let Some(mut prepared) = client.render_state.prepare_frame(&frame) else { + let Some(mut prepared) = client.render_state.prepare_frame(frame) else { client.render_pending = false; crate::render_prof::event("full_render.skip_identical"); crate::render_prof::duration_since("full_render.prepare_frame", prepare_started); continue; }; crate::render_prof::duration_since("full_render.prepare_frame", prepare_started); - let mut frame_to_commit = frame.clone(); - let max_frame_size = if frame.graphics.is_empty() { - MAX_FRAME_SIZE - } else { - MAX_GRAPHICS_FRAME_SIZE - }; let serialize_started = crate::render_prof::timer(); let serialized = match Self::frame_server_message_with_max( prepared.message(), @@ -3031,17 +3031,22 @@ impl HeadlessServer { crate::render_prof::duration_since("full_render.serialize", serialize_started); framed } - Err(protocol::FramingError::Oversized { claimed, max }) - if !frame.graphics.is_empty() => - { + Err(protocol::FramingError::Oversized { claimed, max }) if has_graphics => { warn!( client_id, claimed, max, "dropping graphics from oversized frame for client" ); - let mut text_only_frame = frame.clone(); + let Some(mut text_only_frame) = prepared.into_frame() else { + crate::render_prof::event("full_render.serialize_error"); + crate::render_prof::duration_since( + "full_render.serialize", + serialize_started, + ); + continue; + }; text_only_frame.graphics.clear(); let Some(text_only_prepared) = - client.render_state.prepare_frame(&text_only_frame) + client.render_state.prepare_frame(text_only_frame) else { client.render_pending = false; crate::render_prof::event("full_render.skip_identical_text_only"); @@ -3065,7 +3070,6 @@ impl HeadlessServer { } }; prepared = text_only_prepared; - frame_to_commit = text_only_frame; commit_graphics_cache = false; crate::render_prof::duration_since("full_render.serialize", serialize_started); framed @@ -3097,9 +3101,7 @@ impl HeadlessServer { client.graphics_cache = next_graphics_cache; client.graphics_surface_reset_pending = false; } - client - .render_state - .commit_sent_frame(frame_to_commit, prepared); + client.render_state.commit_sent_frame(prepared); crate::render_prof::event("full_render.sent"); crate::render_prof::duration_since("full_render.try_send", send_started); } @@ -4505,6 +4507,52 @@ next_tab = "" } #[test] + fn terminal_attach_page_key_forwards_in_alternate_screen_without_mouse_reporting() { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("test runtime"); + let _runtime_guard = rt.enter(); + let mut bytes = b"\x1b[?1049h".to_vec(); + for line in 0..80 { + bytes.extend_from_slice(format!("line {line:02}\r\n").as_bytes()); + } + let (runtime, mut input_rx) = + crate::terminal::TerminalRuntime::test_with_channel_and_scrollback_bytes( + 20, 5, 4096, &bytes, 4, + ); + runtime.scroll_up(3); + + apply_terminal_attach_scroll( + &runtime, + AttachScrollSource::PageKey { + input: b"\x1b[5~".to_vec(), + }, + AttachScrollDirection::Up, + 4, + None, + None, + 0, + ) + .expect("page key forward"); + + assert_eq!( + runtime + .scroll_metrics() + .expect("scroll metrics") + .offset_from_bottom, + 0 + ); + assert_eq!( + input_rx.try_recv().expect("forwarded page key"), + Bytes::from_static(b"\x1b[5~") + ); + drop(runtime); + drop(_runtime_guard); + rt.shutdown_timeout(Duration::from_millis(100)); + } + + #[test] fn headless_scheduled_tasks_expire_agent_metadata() { let mut server = test_headless_server(); let workspace = crate::workspace::Workspace::test_new("metadata"); @@ -6384,9 +6432,9 @@ next_tab = "" frame.cells[hyperlink_idx].hyperlink = Some(0); let prepared = client .render_state - .prepare_frame(&frame) + .prepare_frame(frame) .expect("hyperlink frame differs"); - client.render_state.commit_sent_frame(frame, prepared); + client.render_state.commit_sent_frame(prepared); let runtime = server .app |
