mirror of
https://github.com/wez/wezterm.git
synced 2024-12-18 02:42:05 +03:00
ensure that we set the cursor attributes
Set the cursor to match the positioning info reported by the focused widget
This commit is contained in:
parent
837cfae566
commit
b3346b9a43
@ -1,7 +1,10 @@
|
||||
//! This example shows how to make a basic widget that accumulates
|
||||
//! text input and renders it to the screen
|
||||
extern crate failure;
|
||||
extern crate termwiz;
|
||||
|
||||
use failure::Error;
|
||||
use std::cell::Cell;
|
||||
use termwiz::caps::Capabilities;
|
||||
use termwiz::color::AnsiColor;
|
||||
use termwiz::input::*;
|
||||
@ -14,6 +17,7 @@ use termwiz::widgets::*;
|
||||
#[derive(Default)]
|
||||
struct MainScreen {
|
||||
buf: String,
|
||||
cursor: Cell<ParentRelativeCoords>,
|
||||
}
|
||||
|
||||
impl WidgetImpl for MainScreen {
|
||||
@ -45,6 +49,18 @@ impl WidgetImpl for MainScreen {
|
||||
fn render_to_surface(&self, surface: &mut Surface) {
|
||||
surface.add_change(Change::ClearScreen(AnsiColor::Blue.into()));
|
||||
surface.add_change(self.buf.clone());
|
||||
// Allow the surface rendering code to figure out where the
|
||||
// cursor ends up, then stash a copy of that information for
|
||||
// later retrieval by get_cursor_shape_and_position().
|
||||
let (x, y) = surface.cursor_position();
|
||||
self.cursor.set(ParentRelativeCoords::new(x, y));
|
||||
}
|
||||
|
||||
fn get_cursor_shape_and_position(&self) -> CursorShapeAndPosition {
|
||||
CursorShapeAndPosition {
|
||||
coords: self.cursor.get(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use escape::csi::{Cursor, Edit, EraseInDisplay, EraseInLine, Sgr, CSI};
|
||||
use escape::osc::OperatingSystemCommand;
|
||||
use failure;
|
||||
use std::io::{Read, Write};
|
||||
use surface::{Change, Position};
|
||||
use surface::{Change, CursorShape, Position};
|
||||
use terminal::unix::UnixTty;
|
||||
use terminfo::{capability as cap, Capability as TermInfoCapability};
|
||||
|
||||
@ -14,6 +14,8 @@ pub struct TerminfoRenderer {
|
||||
caps: Capabilities,
|
||||
current_attr: CellAttributes,
|
||||
pending_attr: Option<CellAttributes>,
|
||||
/* TODO: we should record cursor position, shape and color here
|
||||
* so that we can optimize updating them on screen. */
|
||||
}
|
||||
|
||||
impl TerminfoRenderer {
|
||||
@ -477,6 +479,39 @@ impl TerminfoRenderer {
|
||||
change
|
||||
);
|
||||
}
|
||||
Change::CursorColor(_color) => {
|
||||
// TODO: this isn't spec'd by terminfo, but some terminals
|
||||
// support it. Add this to capabilities?
|
||||
}
|
||||
Change::CursorShape(shape) => match shape {
|
||||
CursorShape::Default => {
|
||||
if let Some(reset) = self.get_capability::<cap::ResetCursorStyle>() {
|
||||
reset.expand().to(out.by_ref())?;
|
||||
}
|
||||
}
|
||||
CursorShape::Hidden => {
|
||||
if let Some(hide) = self.get_capability::<cap::CursorInvisible>() {
|
||||
hide.expand().to(out.by_ref())?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(show) = self.get_capability::<cap::CursorVisible>() {
|
||||
show.expand().to(out.by_ref())?;
|
||||
}
|
||||
let param = match shape {
|
||||
CursorShape::Default | CursorShape::Hidden => unreachable!(),
|
||||
CursorShape::BlinkingBlock => 1,
|
||||
CursorShape::SteadyBlock => 2,
|
||||
CursorShape::BlinkingUnderline => 3,
|
||||
CursorShape::SteadyUnderline => 4,
|
||||
CursorShape::BlinkingBar => 6,
|
||||
CursorShape::SteadyBar => 7,
|
||||
};
|
||||
if let Some(set) = self.get_capability::<cap::SetCursorStyle>() {
|
||||
set.expand().kind(param).to(out.by_ref())?;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,8 @@ impl WindowsConsoleRenderer {
|
||||
Change::AllAttributes(all) => {
|
||||
self.current_attr = all.clone();
|
||||
}
|
||||
Change::CursorColor(_color) => {}
|
||||
Change::CursorShape(_shape) => {}
|
||||
}
|
||||
}
|
||||
out.flush()?;
|
||||
|
@ -19,6 +19,24 @@ pub enum Position {
|
||||
EndRelative(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CursorShape {
|
||||
Hidden,
|
||||
Default,
|
||||
BlinkingBlock,
|
||||
SteadyBlock,
|
||||
BlinkingUnderline,
|
||||
SteadyUnderline,
|
||||
BlinkingBar,
|
||||
SteadyBar,
|
||||
}
|
||||
|
||||
impl Default for CursorShape {
|
||||
fn default() -> CursorShape {
|
||||
CursorShape::Default
|
||||
}
|
||||
}
|
||||
|
||||
/// `Change` describes an update operation to be applied to a `Surface`.
|
||||
/// Changes to the active attributes (color, style), moving the cursor
|
||||
/// and outputting text are examples of some of the values.
|
||||
@ -52,8 +70,11 @@ pub enum Change {
|
||||
ClearToEndOfScreen(ColorAttribute),
|
||||
/// Move the cursor to the specified `Position`.
|
||||
CursorPosition { x: Position, y: Position },
|
||||
/* CursorVisibility(bool),
|
||||
* ChangeScrollRegion{top: usize, bottom: usize}, */
|
||||
/// Change the cursor color.
|
||||
CursorColor(ColorAttribute),
|
||||
/// Change the cursor shape
|
||||
CursorShape(CursorShape),
|
||||
/* ChangeScrollRegion{top: usize, bottom: usize}, */
|
||||
}
|
||||
|
||||
impl Change {
|
||||
@ -206,6 +227,8 @@ pub struct Surface {
|
||||
ypos: usize,
|
||||
seqno: SequenceNo,
|
||||
changes: Vec<Change>,
|
||||
cursor_shape: CursorShape,
|
||||
cursor_color: ColorAttribute,
|
||||
}
|
||||
|
||||
impl Surface {
|
||||
@ -225,6 +248,10 @@ impl Surface {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
pub fn cursor_position(&self) -> (usize, usize) {
|
||||
(self.xpos, self.ypos)
|
||||
}
|
||||
|
||||
/// Resize the Surface to the specified width and height.
|
||||
/// If the width and/or height are smaller than previously, the rows and/or
|
||||
/// columns are truncated. If the width and/or height are larger than
|
||||
@ -294,6 +321,8 @@ impl Surface {
|
||||
Change::ClearScreen(color) => self.clear_screen(color),
|
||||
Change::ClearToEndOfLine(color) => self.clear_eol(color),
|
||||
Change::ClearToEndOfScreen(color) => self.clear_eos(color),
|
||||
Change::CursorColor(color) => self.cursor_color = color.clone(),
|
||||
Change::CursorShape(shape) => self.cursor_shape = shape.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ impl<T: Terminal> BufferedTerminal<T> {
|
||||
// renders all.
|
||||
self.seqno = 0;
|
||||
self.terminal.render(&changes)?;
|
||||
self.terminal.flush()?;
|
||||
//self.terminal.flush()?;
|
||||
self.seqno = seq;
|
||||
}
|
||||
self.surface.flush_changes_older_than(self.seqno);
|
||||
|
@ -1,7 +1,8 @@
|
||||
use color::ColorAttribute;
|
||||
use input::InputEvent;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::rc::{Rc, Weak};
|
||||
use surface::{SequenceNo, Surface};
|
||||
use surface::{Change, CursorShape, Position, SequenceNo, Surface};
|
||||
|
||||
/// Describes an event that may need to be processed by the widget
|
||||
pub enum WidgetEvent {
|
||||
@ -46,6 +47,13 @@ impl SizeConstraints {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct CursorShapeAndPosition {
|
||||
pub shape: CursorShape,
|
||||
pub coords: ParentRelativeCoords,
|
||||
pub color: ColorAttribute,
|
||||
}
|
||||
|
||||
pub trait WidgetImpl {
|
||||
/// Called once by the widget manager to inform the widget
|
||||
/// of its identifier
|
||||
@ -58,12 +66,17 @@ pub trait WidgetImpl {
|
||||
fn get_size_constraints(&self) -> SizeConstraints;
|
||||
|
||||
fn render_to_surface(&self, surface: &mut Surface);
|
||||
|
||||
/// Called for the focused widget to determine how to render
|
||||
/// the cursor.
|
||||
fn get_cursor_shape_and_position(&self) -> CursorShapeAndPosition;
|
||||
}
|
||||
|
||||
/// Relative to the top left of the parent container
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ParentRelativeCoords {
|
||||
x: usize,
|
||||
y: usize,
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
}
|
||||
|
||||
impl ParentRelativeCoords {
|
||||
@ -73,9 +86,10 @@ impl ParentRelativeCoords {
|
||||
}
|
||||
|
||||
/// Relative to the top left of the screen
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ScreenRelativeCoords {
|
||||
x: usize,
|
||||
y: usize,
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
}
|
||||
|
||||
impl ScreenRelativeCoords {
|
||||
@ -192,6 +206,25 @@ impl Widget {
|
||||
pub fn add_child(&mut self, widget: &WidgetHandle) {
|
||||
self.children.push(widget.clone());
|
||||
}
|
||||
|
||||
pub fn to_screen_coords(&self, coords: &ParentRelativeCoords) -> ScreenRelativeCoords {
|
||||
let mut x = coords.x;
|
||||
let mut y = coords.y;
|
||||
let mut widget = self.parent();
|
||||
loop {
|
||||
let parent = match widget {
|
||||
Some(parent) => {
|
||||
let p = parent.borrow();
|
||||
x += p.coordinates.x;
|
||||
y += p.coordinates.y;
|
||||
p.parent()
|
||||
}
|
||||
None => break,
|
||||
};
|
||||
widget = parent;
|
||||
}
|
||||
ScreenRelativeCoords { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Screen {
|
||||
@ -243,5 +276,18 @@ impl Screen {
|
||||
/// and then progresses up through its children.
|
||||
pub fn render_to_screen(&mut self, screen: &mut Surface) {
|
||||
self.root_widget.borrow_mut().render_to_screen(screen);
|
||||
|
||||
let focused = self.focused_widget.borrow();
|
||||
let cursor = focused.inner.get_cursor_shape_and_position();
|
||||
let coords = focused.to_screen_coords(&cursor.coords);
|
||||
|
||||
screen.add_changes(vec![
|
||||
Change::CursorShape(cursor.shape),
|
||||
Change::CursorColor(cursor.color),
|
||||
Change::CursorPosition {
|
||||
x: Position::Absolute(coords.x),
|
||||
y: Position::Absolute(coords.y),
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user