mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
## What changed Split conversation rendering into preparation, painting, and post-draw steps. Use the supplied conversation bounds for transcript wrapping, composer layout, suggestion overlays, cursor placement, and the empty-state animation. Preserve surrounding text and image placements during input-triggered redraws. Keep centered dialogs relative to the full viewport and restore neighboring content when they close. ## Testing Extend regression tests and add a snapshot for conversations rendered at an offset, covering selection, link hit testing, cursor placement, scroll preservation, neighboring images, and dialog dismissal. GitOrigin-RevId: 0dbca3f8d1064f2d58856c3bc77a4dab1c099cdd
85 lines
3.5 KiB
Rust
85 lines
3.5 KiB
Rust
//! Route registered read-only selections before copy, interrupt, clicks, and paste shortcuts.
|
|
//! A stationary click is replayed to the existing widget handler after selection releases it.
|
|
|
|
use super::*;
|
|
use crate::clipboard_copy::CopyFormat;
|
|
use crate::keymap::ListAction;
|
|
use crate::rendered_selection::RegionAction;
|
|
use crate::rendered_selection::RenderedSelection;
|
|
use crate::transcript_view::ViewAction;
|
|
|
|
impl App {
|
|
pub(super) fn handle_rendered_selection_event(
|
|
&mut self,
|
|
tui: &mut tui::Tui,
|
|
event: &TuiEvent,
|
|
) -> Result<bool> {
|
|
let warning_active = self.chat_widget.keymap_contexts().is_warnings();
|
|
if !tui.is_owned_screen()
|
|
|| self.overlay.is_some()
|
|
|| (!warning_active
|
|
&& (!self.chat_widget.no_modal_or_popup_active()
|
|
|| self.chat_widget.is_external_writer_view()))
|
|
{
|
|
*self.chat_widget.rendered_selection.borrow_mut() = RenderedSelection::default();
|
|
return Ok(false);
|
|
}
|
|
let refresh = matches!(event, TuiEvent::Mouse(mouse)
|
|
if self.chat_widget.rendered_selection.borrow().needs_refresh(*mouse));
|
|
if refresh {
|
|
self.refresh_owned_transcript(tui)?;
|
|
}
|
|
let action = {
|
|
let mut selection = self.chat_widget.rendered_selection.borrow_mut();
|
|
if warning_active
|
|
&& let TuiEvent::Key(key) = event
|
|
&& matches!(
|
|
self.keymap.list.action_for(*key),
|
|
Some(ListAction::PageUp | ListAction::PageDown)
|
|
)
|
|
{
|
|
selection.clear();
|
|
return Ok(false);
|
|
}
|
|
selection.view.copy_on_select = self
|
|
.local_settings
|
|
.copy_on_select(&codex_terminal_detection::terminal_info());
|
|
selection.view.copy_on_select_clear_selection =
|
|
self.local_settings.tui.copy_on_select_clear_selection;
|
|
selection.view.primary_selection = self.right_click_paste_environment.primary;
|
|
selection.handle_event(event, tui.terminal.previous_buffer())
|
|
};
|
|
let Some(action) = action else {
|
|
return Ok(false);
|
|
};
|
|
if warning_active {
|
|
self.chat_widget.record_warning_activity();
|
|
}
|
|
self.cancel_pending_key_chord();
|
|
match action {
|
|
RegionAction::Click(mouse) => {
|
|
self.chat_widget
|
|
.handle_warning_event(&TuiEvent::Mouse(mouse), &self.transcript_cells);
|
|
}
|
|
RegionAction::Selection(action) => {
|
|
self.transcript_view.end_selection(&self.transcript_cells);
|
|
self.transcript_view.cancel_search();
|
|
self.transcript_view.clear_activity_focus();
|
|
self.chat_widget.clear_composer_selection();
|
|
let copied = {
|
|
let mut selection = self.chat_widget.rendered_selection.borrow_mut();
|
|
let RenderedSelection { view, cells, .. } = &mut *selection;
|
|
view.copy_action(tui, cells, &action, CopyFormat::PlainText)
|
|
};
|
|
if let Some((characters, result)) = copied {
|
|
self.transcript_view.show_copy_feedback(&result, characters);
|
|
} else if let ViewAction::OpenLink(url) = action {
|
|
self.open_url_in_browser(url);
|
|
}
|
|
}
|
|
}
|
|
tui.frame_requester().schedule_frame();
|
|
Ok(true)
|
|
}
|
|
}
|