1
1
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:
Wez Furlong 2020-01-03 09:54:27 -08:00
parent 12b537d2c8
commit 4912e83f3e
6 changed files with 69 additions and 54 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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>)> {

View File

@ -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),

View File

@ -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,
}
}

View File

@ -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,
}
}