mirror of
https://github.com/wez/wezterm.git
synced 2024-09-20 03:09:06 +03:00
StableCursorPosition to track the cursor
This fixes up the cursor position when scrolling. refs: https://github.com/wez/wezterm/issues/106
This commit is contained in:
parent
12b537d2c8
commit
4912e83f3e
@ -93,7 +93,6 @@ impl ScrollHit {
|
||||
dims: &Dimensions,
|
||||
) -> StableRowIndex {
|
||||
let render_dims = render.get_dimensions();
|
||||
let scroll_size = render_dims.scrollback_rows;
|
||||
let thumb = Self::thumb(render, viewport, size, dims);
|
||||
|
||||
let rows_from_top = ((thumb_top as f32) / thumb.height as f32) * thumb.rows as f32;
|
||||
|
@ -8,7 +8,7 @@ use crate::frontend::gui::scrollbar::*;
|
||||
use crate::frontend::gui::tabbar::{TabBarItem, TabBarState};
|
||||
use crate::frontend::{executor, front_end};
|
||||
use crate::keyassignment::{KeyAssignment, KeyMap, SpawnTabDomain};
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions};
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::WindowId as MuxWindowId;
|
||||
use crate::mux::Mux;
|
||||
@ -28,7 +28,7 @@ use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
use term::color::ColorPalette;
|
||||
use term::{CursorPosition, Line, StableRowIndex, Underline};
|
||||
use term::{Line, StableRowIndex, Underline};
|
||||
use termwiz::color::RgbColor;
|
||||
use termwiz::surface::CursorShape;
|
||||
|
||||
@ -70,14 +70,14 @@ impl term::Clipboard for ClipboardHelper {
|
||||
}
|
||||
|
||||
struct PrevCursorPos {
|
||||
pos: CursorPosition,
|
||||
pos: StableCursorPosition,
|
||||
when: Instant,
|
||||
}
|
||||
|
||||
impl PrevCursorPos {
|
||||
fn new() -> Self {
|
||||
PrevCursorPos {
|
||||
pos: CursorPosition::default(),
|
||||
pos: StableCursorPosition::default(),
|
||||
when: Instant::now(),
|
||||
}
|
||||
}
|
||||
@ -88,7 +88,7 @@ impl PrevCursorPos {
|
||||
}
|
||||
|
||||
/// Update the cursor position if its different
|
||||
fn update(&mut self, newpos: &CursorPosition) {
|
||||
fn update(&mut self, newpos: &StableCursorPosition) {
|
||||
if &self.pos != newpos {
|
||||
self.pos = *newpos;
|
||||
self.when = Instant::now();
|
||||
@ -1401,23 +1401,26 @@ impl TermWindow {
|
||||
let first_line_offset = if self.show_tab_bar { 1 } else { 0 };
|
||||
|
||||
let mut term = tab.renderer();
|
||||
let cursor = {
|
||||
let cursor = term.get_cursor_position();
|
||||
CursorPosition {
|
||||
x: cursor.x,
|
||||
y: cursor.y + first_line_offset as i64,
|
||||
..cursor
|
||||
}
|
||||
};
|
||||
let cursor = term.get_cursor_position();
|
||||
self.prev_cursor.update(&cursor);
|
||||
let current_viewport = self.get_viewport(tab.tab_id());
|
||||
|
||||
let dims = term.get_dimensions();
|
||||
|
||||
if self.show_tab_bar {
|
||||
self.render_screen_line(ctx, 0, self.tab_bar.line(), 0..0, &cursor, &*term, &palette)?;
|
||||
self.render_screen_line(
|
||||
ctx,
|
||||
0,
|
||||
dims.physical_top,
|
||||
self.tab_bar.line(),
|
||||
0..0,
|
||||
&cursor,
|
||||
&*term,
|
||||
&palette,
|
||||
)?;
|
||||
}
|
||||
|
||||
{
|
||||
let dims = term.get_dimensions();
|
||||
let stable_range = match current_viewport {
|
||||
Some(top) => top..top + dims.viewport_rows as StableRowIndex,
|
||||
None => dims.physical_top..dims.physical_top + dims.viewport_rows as StableRowIndex,
|
||||
@ -1432,9 +1435,10 @@ impl TermWindow {
|
||||
self.render_screen_line(
|
||||
ctx,
|
||||
line_idx + first_line_offset,
|
||||
stable_top + line_idx as StableRowIndex,
|
||||
&line,
|
||||
selrange,
|
||||
&cursor, // FIXME: cursor offset when scrolling
|
||||
&cursor,
|
||||
&*term,
|
||||
&palette,
|
||||
)?;
|
||||
@ -1554,21 +1558,14 @@ impl TermWindow {
|
||||
let first_line_offset = if self.show_tab_bar { 1 } else { 0 };
|
||||
|
||||
let mut term = tab.renderer();
|
||||
let cursor = {
|
||||
let cursor = term.get_cursor_position();
|
||||
CursorPosition {
|
||||
x: cursor.x,
|
||||
y: cursor.y + first_line_offset as i64,
|
||||
..cursor
|
||||
}
|
||||
};
|
||||
let cursor = term.get_cursor_position();
|
||||
self.prev_cursor.update(&cursor);
|
||||
|
||||
let current_viewport = self.get_viewport(tab.tab_id());
|
||||
let (stable_top, lines);
|
||||
let dims = term.get_dimensions();
|
||||
|
||||
{
|
||||
let dims = term.get_dimensions();
|
||||
let stable_range = match current_viewport {
|
||||
Some(top) => top..top + dims.viewport_rows as StableRowIndex,
|
||||
None => dims.physical_top..dims.physical_top + dims.viewport_rows as StableRowIndex,
|
||||
@ -1586,6 +1583,7 @@ impl TermWindow {
|
||||
if self.show_tab_bar {
|
||||
self.render_screen_line_opengl(
|
||||
0,
|
||||
dims.physical_top,
|
||||
self.tab_bar.line(),
|
||||
0..0,
|
||||
&cursor,
|
||||
@ -1643,9 +1641,10 @@ impl TermWindow {
|
||||
|
||||
self.render_screen_line_opengl(
|
||||
line_idx + first_line_offset,
|
||||
stable_top + line_idx as StableRowIndex,
|
||||
&line,
|
||||
selrange,
|
||||
&cursor, // FIXME: cursor offset when scrolling
|
||||
&cursor,
|
||||
&*term,
|
||||
&palette,
|
||||
&mut quads,
|
||||
@ -1732,9 +1731,10 @@ impl TermWindow {
|
||||
fn render_screen_line_opengl(
|
||||
&self,
|
||||
line_idx: usize,
|
||||
stable_line_idx: StableRowIndex,
|
||||
line: &Line,
|
||||
selection: Range<usize>,
|
||||
cursor: &CursorPosition,
|
||||
cursor: &StableCursorPosition,
|
||||
terminal: &dyn Renderable,
|
||||
palette: &ColorPalette,
|
||||
quads: &mut MappedQuads,
|
||||
@ -1840,7 +1840,7 @@ impl TermWindow {
|
||||
last_cell_idx = cell_idx;
|
||||
|
||||
let (glyph_color, bg_color, cursor_shape) = self.compute_cell_fg_bg(
|
||||
line_idx,
|
||||
stable_line_idx,
|
||||
cell_idx,
|
||||
cursor,
|
||||
&selection,
|
||||
@ -1952,7 +1952,7 @@ impl TermWindow {
|
||||
// hold the cursor or the selection so we need to compute
|
||||
// the colors in the usual way.
|
||||
let (glyph_color, bg_color, cursor_shape) = self.compute_cell_fg_bg(
|
||||
line_idx,
|
||||
stable_line_idx,
|
||||
cell_idx,
|
||||
cursor,
|
||||
&selection,
|
||||
@ -1986,9 +1986,10 @@ impl TermWindow {
|
||||
&self,
|
||||
ctx: &mut dyn PaintContext,
|
||||
line_idx: usize,
|
||||
stable_line_idx: StableRowIndex,
|
||||
line: &Line,
|
||||
selection: Range<usize>,
|
||||
cursor: &CursorPosition,
|
||||
cursor: &StableCursorPosition,
|
||||
terminal: &dyn Renderable,
|
||||
palette: &ColorPalette,
|
||||
) -> anyhow::Result<()> {
|
||||
@ -2090,7 +2091,7 @@ impl TermWindow {
|
||||
last_cell_idx = cell_idx;
|
||||
|
||||
let (glyph_color, bg_color, cursor_shape) = self.compute_cell_fg_bg(
|
||||
line_idx,
|
||||
stable_line_idx,
|
||||
cell_idx,
|
||||
cursor,
|
||||
&selection,
|
||||
@ -2212,7 +2213,7 @@ impl TermWindow {
|
||||
// hold the cursor or the selection so we need to compute
|
||||
// the colors in the usual way.
|
||||
let (_glyph_color, bg_color, cursor_shape) = self.compute_cell_fg_bg(
|
||||
line_idx,
|
||||
stable_line_idx,
|
||||
cell_idx,
|
||||
cursor,
|
||||
&selection,
|
||||
@ -2267,9 +2268,9 @@ impl TermWindow {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn compute_cell_fg_bg(
|
||||
&self,
|
||||
line_idx: usize,
|
||||
stable_line_idx: StableRowIndex,
|
||||
cell_idx: usize,
|
||||
cursor: &CursorPosition,
|
||||
cursor: &StableCursorPosition,
|
||||
selection: &Range<usize>,
|
||||
fg_color: Color,
|
||||
bg_color: Color,
|
||||
@ -2277,7 +2278,7 @@ impl TermWindow {
|
||||
) -> (Color, Color, CursorShape) {
|
||||
let selected = selection.contains(&cell_idx);
|
||||
|
||||
let is_cursor = line_idx as i64 == cursor.y && cursor.x == cell_idx;
|
||||
let is_cursor = stable_line_idx == cursor.y && cursor.x == cell_idx;
|
||||
|
||||
let cursor_shape = if is_cursor {
|
||||
// This logic figures out whether the cursor is visible or not.
|
||||
|
@ -1,10 +1,19 @@
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use term::{CursorPosition, Line, StableRowIndex, Terminal, TerminalState, VisibleRowIndex};
|
||||
use term::{Line, StableRowIndex, Terminal, TerminalState, VisibleRowIndex};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
|
||||
/// Describes the location of the cursor
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct StableCursorPosition {
|
||||
pub x: usize,
|
||||
pub y: StableRowIndex,
|
||||
pub shape: termwiz::surface::CursorShape,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct RenderableDimensions {
|
||||
/// The viewport width
|
||||
@ -29,7 +38,7 @@ pub struct RenderableDimensions {
|
||||
pub trait Renderable: Downcast {
|
||||
/// Returns the 0-based cursor position relative to the top left of
|
||||
/// the visible screen
|
||||
fn get_cursor_position(&self) -> CursorPosition;
|
||||
fn get_cursor_position(&self) -> StableCursorPosition;
|
||||
|
||||
/// Returns the set of visible lines that are dirty.
|
||||
/// The return value is a Vec<(line_idx, line, selrange)>, where
|
||||
@ -69,8 +78,14 @@ pub trait Renderable: Downcast {
|
||||
impl_downcast!(Renderable);
|
||||
|
||||
impl Renderable for Terminal {
|
||||
fn get_cursor_position(&self) -> CursorPosition {
|
||||
self.cursor_pos()
|
||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||
let pos = self.cursor_pos();
|
||||
|
||||
StableCursorPosition {
|
||||
x: pos.x,
|
||||
y: self.screen().visible_row_to_stable_row(pos.y),
|
||||
shape: pos.shape,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dirty_lines(&self) -> Vec<(usize, Cow<Line>, Range<usize>)> {
|
||||
|
@ -26,6 +26,7 @@ use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Instant;
|
||||
use term::terminal::Clipboard;
|
||||
use term::StableRowIndex;
|
||||
use termwiz::surface::{Change, Position, SequenceNo, Surface};
|
||||
|
||||
struct LocalListener {
|
||||
@ -447,10 +448,10 @@ impl ClientSurfaceState {
|
||||
|
||||
let (x, y) = self.surface.cursor_position();
|
||||
let cursor = renderable.get_cursor_position();
|
||||
if (x != cursor.x) || (y as i64 != cursor.y) {
|
||||
if (x != cursor.x) || (y as StableRowIndex != cursor.y) {
|
||||
// Update the cursor, but if we're scrolled back
|
||||
// and it is our of range, skip the update.
|
||||
if cursor.y < dims.viewport_rows as i64 {
|
||||
if cursor.y < dims.viewport_rows as StableRowIndex {
|
||||
self.surface.add_change(Change::CursorPosition {
|
||||
x: Position::Absolute(cursor.x),
|
||||
y: Position::Absolute(cursor.y as usize),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::config::configuration;
|
||||
use crate::frontend::executor;
|
||||
use crate::mux::domain::DomainId;
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions};
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
|
||||
use crate::mux::tab::{alloc_tab_id, Tab, TabId};
|
||||
use crate::server::client::Client;
|
||||
use crate::server::codec::*;
|
||||
@ -23,8 +23,8 @@ use std::time::{Duration, Instant};
|
||||
use term::color::ColorPalette;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{
|
||||
Clipboard, CursorPosition, KeyCode, KeyModifiers, Line, MouseButton, MouseEvent,
|
||||
MouseEventKind, StableRowIndex, TerminalHost, VisibleRowIndex,
|
||||
Clipboard, KeyCode, KeyModifiers, Line, MouseButton, MouseEvent, MouseEventKind,
|
||||
StableRowIndex, TerminalHost, VisibleRowIndex,
|
||||
};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
use termwiz::input::KeyEvent;
|
||||
@ -408,13 +408,13 @@ impl RenderableInner {
|
||||
}
|
||||
|
||||
impl Renderable for RenderableState {
|
||||
fn get_cursor_position(&self) -> CursorPosition {
|
||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||
let surface = &self.inner.borrow().surface;
|
||||
let (x, y) = surface.cursor_position();
|
||||
let shape = surface.cursor_shape();
|
||||
CursorPosition {
|
||||
StableCursorPosition {
|
||||
x,
|
||||
y: y as i64,
|
||||
y: y as StableRowIndex,
|
||||
shape,
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
use crate::font::FontConfiguration;
|
||||
use crate::frontend::{executor, front_end};
|
||||
use crate::mux::domain::{alloc_domain_id, Domain, DomainId, DomainState};
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions};
|
||||
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
|
||||
use crate::mux::tab::{alloc_tab_id, Tab, TabId};
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
@ -27,8 +27,7 @@ use std::time::Duration;
|
||||
use term::color::ColorPalette;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{
|
||||
CursorPosition, KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex, TerminalHost,
|
||||
VisibleRowIndex,
|
||||
KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex, TerminalHost, VisibleRowIndex,
|
||||
};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
use termwiz::input::{InputEvent, KeyEvent};
|
||||
@ -67,13 +66,13 @@ impl std::io::Write for RenderableState {
|
||||
}
|
||||
|
||||
impl Renderable for RenderableState {
|
||||
fn get_cursor_position(&self) -> CursorPosition {
|
||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||
let surface = &self.inner.borrow().surface;
|
||||
let (x, y) = surface.cursor_position();
|
||||
let shape = surface.cursor_shape();
|
||||
CursorPosition {
|
||||
StableCursorPosition {
|
||||
x,
|
||||
y: y as i64,
|
||||
y: y as StableRowIndex,
|
||||
shape,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user