Support for blinkwait gui cursor setting
This commit is contained in:
parent
83ca7bf342
commit
354bfce670
@ -10,6 +10,7 @@ use cairo;
|
||||
|
||||
use neovim_lib::Value;
|
||||
|
||||
use mode;
|
||||
use ui_model::{Attrs, ModelLayout};
|
||||
use ui::UiMutex;
|
||||
use render::{self, CellMetrics};
|
||||
@ -386,15 +387,24 @@ impl CmdLine {
|
||||
state.request_area_size();
|
||||
}
|
||||
|
||||
pub fn block_hide(&mut self) {
|
||||
pub fn block_hide(&self) {
|
||||
self.state.borrow_mut().block = None;
|
||||
}
|
||||
|
||||
pub fn pos(&mut self, render_state: &shell::RenderState, pos: u64, level: u64) {
|
||||
pub fn pos(&self, render_state: &shell::RenderState, pos: u64, level: u64) {
|
||||
self.state
|
||||
.borrow_mut()
|
||||
.set_cursor(render_state, pos as usize, level as usize);
|
||||
}
|
||||
|
||||
pub fn set_mode_info(&self, mode_info: Option<mode::ModeInfo>) {
|
||||
self.state
|
||||
.borrow_mut()
|
||||
.cursor
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_mode_info(mode_info);
|
||||
}
|
||||
}
|
||||
|
||||
fn gtk_draw(ctx: &cairo::Context, state: &Arc<UiMutex<State>>) -> Inhibit {
|
||||
@ -419,7 +429,6 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc<UiMutex<State>>) -> Inhibit {
|
||||
&render_state.font_ctx,
|
||||
&block.model_layout.model,
|
||||
&render_state.color_model,
|
||||
&render_state.mode,
|
||||
);
|
||||
|
||||
ctx.translate(0.0, block.preferred_height as f64);
|
||||
@ -432,7 +441,6 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc<UiMutex<State>>) -> Inhibit {
|
||||
&render_state.font_ctx,
|
||||
&level.model_layout.model,
|
||||
&render_state.color_model,
|
||||
&render_state.mode,
|
||||
);
|
||||
}
|
||||
Inhibit(false)
|
||||
|
@ -2,7 +2,6 @@ use cairo;
|
||||
use color::Color;
|
||||
use ui::UiMutex;
|
||||
use mode;
|
||||
use nvim;
|
||||
use std::sync::{Arc, Weak};
|
||||
use render;
|
||||
use render::CellMetrics;
|
||||
@ -74,7 +73,6 @@ pub trait Cursor {
|
||||
&self,
|
||||
ctx: &cairo::Context,
|
||||
font_ctx: &render::Context,
|
||||
mode: &mode::Mode,
|
||||
line_y: f64,
|
||||
double_width: bool,
|
||||
bg: &Color,
|
||||
@ -94,7 +92,6 @@ impl Cursor for EmptyCursor {
|
||||
&self,
|
||||
_ctx: &cairo::Context,
|
||||
_font_ctx: &render::Context,
|
||||
_mode: &mode::Mode,
|
||||
_line_y: f64,
|
||||
_double_width: bool,
|
||||
_bg: &Color,
|
||||
@ -104,20 +101,34 @@ impl Cursor for EmptyCursor {
|
||||
|
||||
pub struct BlinkCursor<CB: CursorRedrawCb> {
|
||||
state: Arc<UiMutex<State<CB>>>,
|
||||
mode_info: Option<mode::ModeInfo>,
|
||||
}
|
||||
|
||||
impl<CB: CursorRedrawCb + 'static> BlinkCursor<CB> {
|
||||
pub fn new(redraw_cb: Weak<UiMutex<CB>>) -> Self {
|
||||
BlinkCursor {
|
||||
state: Arc::new(UiMutex::new(State::new(redraw_cb))),
|
||||
mode_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_mode_info(&mut self, mode_info: Option<mode::ModeInfo>) {
|
||||
self.mode_info = mode_info;
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
let blinkwait = self.mode_info
|
||||
.as_ref()
|
||||
.and_then(|mi| mi.blinkwait)
|
||||
.unwrap_or(500);
|
||||
|
||||
let state = self.state.clone();
|
||||
let mut mut_state = self.state.borrow_mut();
|
||||
mut_state.reset_to(AnimPhase::Shown);
|
||||
mut_state.timer = Some(glib::timeout_add(500, move || anim_step(&state)));
|
||||
mut_state.timer = Some(glib::timeout_add(
|
||||
if blinkwait > 0 { blinkwait } else { 500 },
|
||||
move || anim_step(&state),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn reset_state(&mut self) {
|
||||
@ -152,7 +163,6 @@ impl<CB: CursorRedrawCb> Cursor for BlinkCursor<CB> {
|
||||
&self,
|
||||
ctx: &cairo::Context,
|
||||
font_ctx: &render::Context,
|
||||
mode: &mode::Mode,
|
||||
line_y: f64,
|
||||
double_width: bool,
|
||||
bg: &Color,
|
||||
@ -166,7 +176,12 @@ impl<CB: CursorRedrawCb> Cursor for BlinkCursor<CB> {
|
||||
let current_point = ctx.get_current_point();
|
||||
ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0);
|
||||
|
||||
let (y, width, height) = cursor_rect(mode, font_ctx.cell_metrics(), line_y, double_width);
|
||||
let (y, width, height) = cursor_rect(
|
||||
self.mode_info.as_ref(),
|
||||
font_ctx.cell_metrics(),
|
||||
line_y,
|
||||
double_width,
|
||||
);
|
||||
|
||||
ctx.rectangle(current_point.0, y, width, height);
|
||||
if state.anim_phase == AnimPhase::NoFocus {
|
||||
@ -178,7 +193,7 @@ impl<CB: CursorRedrawCb> Cursor for BlinkCursor<CB> {
|
||||
}
|
||||
|
||||
fn cursor_rect(
|
||||
mode: &mode::Mode,
|
||||
mode_info: Option<&mode::ModeInfo>,
|
||||
cell_metrics: &CellMetrics,
|
||||
line_y: f64,
|
||||
double_width: bool,
|
||||
@ -189,9 +204,9 @@ fn cursor_rect(
|
||||
..
|
||||
} = cell_metrics;
|
||||
|
||||
if let Some(mode_info) = mode.mode_info() {
|
||||
if let Some(mode_info) = mode_info {
|
||||
match mode_info.cursor_shape() {
|
||||
None | Some(&nvim::CursorShape::Unknown) | Some(&nvim::CursorShape::Block) => {
|
||||
None | Some(&mode::CursorShape::Unknown) | Some(&mode::CursorShape::Block) => {
|
||||
let cursor_width = if double_width {
|
||||
char_width * 2.0
|
||||
} else {
|
||||
@ -199,7 +214,7 @@ fn cursor_rect(
|
||||
};
|
||||
(line_y, cursor_width, line_height)
|
||||
}
|
||||
Some(&nvim::CursorShape::Vertical) => {
|
||||
Some(&mode::CursorShape::Vertical) => {
|
||||
let cell_percentage = mode_info.cell_percentage();
|
||||
let cursor_width = if cell_percentage > 0 {
|
||||
(char_width * cell_percentage as f64) / 100.0
|
||||
@ -208,7 +223,7 @@ fn cursor_rect(
|
||||
};
|
||||
(line_y, cursor_width, line_height)
|
||||
}
|
||||
Some(&nvim::CursorShape::Horizontal) => {
|
||||
Some(&mode::CursorShape::Horizontal) => {
|
||||
let cell_percentage = mode_info.cell_percentage();
|
||||
let cursor_width = if double_width {
|
||||
char_width * 2.0
|
||||
@ -225,9 +240,7 @@ fn cursor_rect(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let cursor_width = if mode.is(&mode::NvimMode::Insert) {
|
||||
char_width / 5.0
|
||||
} else if double_width {
|
||||
let cursor_width = if double_width {
|
||||
char_width * 2.0
|
||||
} else {
|
||||
char_width
|
||||
@ -272,7 +285,6 @@ fn anim_step<CB: CursorRedrawCb + 'static>(state: &Arc<UiMutex<State<CB>>>) -> g
|
||||
let mut redraw_cb = redraw_cb.borrow_mut();
|
||||
redraw_cb.queue_redraw_cursor();
|
||||
|
||||
|
||||
if let Some(timeout) = next_event {
|
||||
let moved_state = state.clone();
|
||||
mut_state.timer = Some(glib::timeout_add(timeout, move || anim_step(&moved_state)));
|
||||
|
69
src/mode.rs
69
src/mode.rs
@ -1,6 +1,7 @@
|
||||
use nvim;
|
||||
use std::collections::HashMap;
|
||||
use neovim_lib::Value;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum NvimMode {
|
||||
Normal,
|
||||
Insert,
|
||||
@ -10,7 +11,7 @@ pub enum NvimMode {
|
||||
pub struct Mode {
|
||||
mode: NvimMode,
|
||||
idx: usize,
|
||||
info: Option<Vec<nvim::ModeInfo>>,
|
||||
info: Option<Vec<ModeInfo>>,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
@ -26,7 +27,7 @@ impl Mode {
|
||||
self.mode == *mode
|
||||
}
|
||||
|
||||
pub fn mode_info(&self) -> Option<&nvim::ModeInfo> {
|
||||
pub fn mode_info(&self) -> Option<&ModeInfo> {
|
||||
self.info.as_ref().and_then(|i| i.get(self.idx))
|
||||
}
|
||||
|
||||
@ -40,7 +41,7 @@ impl Mode {
|
||||
self.idx = idx;
|
||||
}
|
||||
|
||||
pub fn set_info(&mut self, cursor_style_enabled: bool, info: Vec<nvim::ModeInfo>) {
|
||||
pub fn set_info(&mut self, cursor_style_enabled: bool, info: Vec<ModeInfo>) {
|
||||
self.info = if cursor_style_enabled {
|
||||
Some(info)
|
||||
} else {
|
||||
@ -48,3 +49,61 @@ impl Mode {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum CursorShape {
|
||||
Block,
|
||||
Horizontal,
|
||||
Vertical,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl CursorShape {
|
||||
fn new(shape_code: &Value) -> Result<CursorShape, String> {
|
||||
let str_code = shape_code
|
||||
.as_str()
|
||||
.ok_or_else(|| "Can't convert cursor shape to string".to_owned())?;
|
||||
|
||||
Ok(match str_code {
|
||||
"block" => CursorShape::Block,
|
||||
"horizontal" => CursorShape::Horizontal,
|
||||
"vertical" => CursorShape::Vertical,
|
||||
_ => {
|
||||
error!("Unknown cursor_shape {}", str_code);
|
||||
CursorShape::Unknown
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ModeInfo {
|
||||
cursor_shape: Option<CursorShape>,
|
||||
cell_percentage: Option<u64>,
|
||||
pub blinkwait: Option<u32>,
|
||||
}
|
||||
|
||||
impl ModeInfo {
|
||||
pub fn new(mode_info_map: &HashMap<String, Value>) -> Result<Self, String> {
|
||||
let cursor_shape = if let Some(shape) = mode_info_map.get("cursor_shape") {
|
||||
Some(CursorShape::new(shape)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(ModeInfo {
|
||||
cursor_shape,
|
||||
cell_percentage: mode_info_map.get("cell_percentage").and_then(|cp| cp.as_u64()),
|
||||
blinkwait: mode_info_map.get("blinkwait").and_then(|cp| cp.as_u64()).map(|v| v as u32),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cursor_shape(&self) -> Option<&CursorShape> {
|
||||
self.cursor_shape.as_ref()
|
||||
}
|
||||
|
||||
pub fn cell_percentage(&self) -> u64 {
|
||||
self.cell_percentage.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
mod client;
|
||||
mod handler;
|
||||
mod mode_info;
|
||||
mod redraw_handler;
|
||||
mod repaint_mode;
|
||||
mod ext;
|
||||
@ -8,7 +7,6 @@ mod ext;
|
||||
pub use self::redraw_handler::CompleteItem;
|
||||
pub use self::repaint_mode::RepaintMode;
|
||||
pub use self::client::{NeovimClient, NeovimClientAsync, NeovimRef};
|
||||
pub use self::mode_info::{CursorShape, ModeInfo};
|
||||
pub use self::ext::ErrorReport;
|
||||
pub use self::handler::NvimHandler;
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
use neovim_lib::Value;
|
||||
|
||||
use value::ValueMapExt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CursorShape {
|
||||
Block,
|
||||
Horizontal,
|
||||
Vertical,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl CursorShape {
|
||||
fn new(shape_code: &Value) -> Result<CursorShape, String> {
|
||||
let str_code = shape_code
|
||||
.as_str()
|
||||
.ok_or_else(|| "Can't convert cursor shape to string".to_owned())?;
|
||||
|
||||
Ok(match str_code {
|
||||
"block" => CursorShape::Block,
|
||||
"horizontal" => CursorShape::Horizontal,
|
||||
"vertical" => CursorShape::Vertical,
|
||||
_ => {
|
||||
error!("Unknown cursor_shape {}", str_code);
|
||||
CursorShape::Unknown
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModeInfo {
|
||||
cursor_shape: Option<CursorShape>,
|
||||
cell_percentage: Option<u64>,
|
||||
}
|
||||
|
||||
impl ModeInfo {
|
||||
pub fn new(mode_info_arr: &Vec<(Value, Value)>) -> Result<Self, String> {
|
||||
let mode_info_map = mode_info_arr.to_attrs_map()?;
|
||||
|
||||
let cursor_shape = if let Some(shape) = mode_info_map.get("cursor_shape") {
|
||||
Some(CursorShape::new(shape)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cell_percentage = if let Some(cell_percentage) = mode_info_map.get("cell_percentage") {
|
||||
cell_percentage.as_u64()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(ModeInfo {
|
||||
cursor_shape,
|
||||
cell_percentage,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cursor_shape(&self) -> Option<&CursorShape> {
|
||||
self.cursor_shape.as_ref()
|
||||
}
|
||||
|
||||
pub fn cell_percentage(&self) -> u64 {
|
||||
self.cell_percentage.unwrap_or(0)
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@ use value::ValueMapExt;
|
||||
use rmpv;
|
||||
|
||||
use super::repaint_mode::RepaintMode;
|
||||
use super::mode_info::ModeInfo;
|
||||
use super::handler::NvimHandler;
|
||||
|
||||
macro_rules! try_str {
|
||||
@ -222,16 +221,7 @@ pub fn call(
|
||||
})?;
|
||||
ui.tabline_update(Tabpage::new(args[0].clone()), tabs_out)
|
||||
}
|
||||
"mode_info_set" => {
|
||||
let mode_info = map_array!(
|
||||
args[1],
|
||||
"Error get array key value for mode_info".to_owned(),
|
||||
|mi| mi.as_map()
|
||||
.ok_or_else(|| "Erro get map for mode_info".to_owned())
|
||||
.and_then(|mi_map| ModeInfo::new(mi_map))
|
||||
)?;
|
||||
ui.mode_info_set(try_bool!(args[0]), mode_info)
|
||||
}
|
||||
"mode_info_set" => call!(ui->mode_info_set(args: bool, ext)),
|
||||
"cmdline_show" => call!(ui->cmdline_show(args: ext, uint, str, str, uint, uint)),
|
||||
"cmdline_block_show" => call!(ui->cmdline_block_show(args: ext)),
|
||||
"cmdline_block_append" => call!(ui->cmdline_block_append(args: ext)),
|
||||
@ -251,10 +241,10 @@ pub fn call(
|
||||
// Here two cases processed:
|
||||
//
|
||||
// 1. menu content update call popupmenu_hide followed by popupmenu_show in same batch
|
||||
// this generates unneded hide event
|
||||
// this generates unneeded hide event
|
||||
// so in case we get both events, just romove one
|
||||
//
|
||||
// 2. hide event postpone in case show event come bit later
|
||||
// 2. postpone hide event when "show" event come bit later
|
||||
// but in new event batch
|
||||
pub fn remove_or_delay_uneeded_events(handler: &NvimHandler, params: &mut Vec<Value>) {
|
||||
let mut show_popup_finded = false;
|
||||
|
@ -6,7 +6,6 @@ pub use self::context::Context;
|
||||
pub use self::context::CellMetrics;
|
||||
use self::model_clip_iterator::{ModelClipIteratorFactory, RowView};
|
||||
|
||||
use mode;
|
||||
use color;
|
||||
use sys::pango::*;
|
||||
use sys::pangocairo::*;
|
||||
@ -32,7 +31,6 @@ pub fn render<C: Cursor>(
|
||||
font_ctx: &context::Context,
|
||||
ui_model: &ui_model::UiModel,
|
||||
color_model: &color::ColorModel,
|
||||
mode: &mode::Mode,
|
||||
) {
|
||||
let cell_metrics = font_ctx.cell_metrics();
|
||||
let &CellMetrics { char_width, .. } = cell_metrics;
|
||||
@ -66,7 +64,6 @@ pub fn render<C: Cursor>(
|
||||
cursor.draw(
|
||||
ctx,
|
||||
font_ctx,
|
||||
mode,
|
||||
line_y,
|
||||
double_width,
|
||||
color_model.actual_cell_bg(cell),
|
||||
|
33
src/shell.rs
33
src/shell.rs
@ -27,6 +27,7 @@ use ui_model::{Attrs, ModelRect, UiModel};
|
||||
use color::{Color, ColorModel, COLOR_BLACK, COLOR_RED, COLOR_WHITE};
|
||||
use nvim::{self, CompleteItem, ErrorReport, NeovimClient, NeovimClientAsync, NeovimRef,
|
||||
NvimHandler, RepaintMode};
|
||||
|
||||
use input;
|
||||
use input::keyval_to_input_string;
|
||||
use cursor::{BlinkCursor, Cursor, CursorRedrawCb};
|
||||
@ -119,8 +120,6 @@ pub struct State {
|
||||
pub clipboard_clipboard: gtk::Clipboard,
|
||||
pub clipboard_primary: gtk::Clipboard,
|
||||
|
||||
pub mode: mode::Mode,
|
||||
|
||||
stack: gtk::Stack,
|
||||
pub drawing_area: gtk::DrawingArea,
|
||||
tabs: Tabline,
|
||||
@ -165,8 +164,6 @@ impl State {
|
||||
clipboard_clipboard: gtk::Clipboard::get(&gdk::Atom::intern("CLIPBOARD")),
|
||||
clipboard_primary: gtk::Clipboard::get(&gdk::Atom::intern("PRIMARY")),
|
||||
|
||||
mode: mode::Mode::new(),
|
||||
|
||||
// UI
|
||||
stack: gtk::Stack::new(),
|
||||
drawing_area,
|
||||
@ -947,7 +944,6 @@ fn gtk_draw_double_buffer(state: &State, ctx: &cairo::Context) {
|
||||
&render_state.font_ctx,
|
||||
&state.model,
|
||||
&render_state.color_model,
|
||||
&render_state.mode,
|
||||
);
|
||||
|
||||
ctx.set_source_surface(&surface.surface, 0.0, 0.0);
|
||||
@ -964,7 +960,6 @@ fn gtk_draw_direct(state: &State, ctx: &cairo::Context) {
|
||||
&render_state.font_ctx,
|
||||
&state.model,
|
||||
&render_state.color_model,
|
||||
&render_state.mode,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1130,7 +1125,6 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
||||
state.cursor.as_ref().unwrap().draw(
|
||||
ctx,
|
||||
&render_state.font_ctx,
|
||||
&render_state.mode,
|
||||
y,
|
||||
false,
|
||||
&color_model.bg_color,
|
||||
@ -1259,6 +1253,12 @@ impl State {
|
||||
pub fn on_mode_change(&mut self, mode: String, idx: u64) -> RepaintMode {
|
||||
let mut render_state = self.render_state.borrow_mut();
|
||||
render_state.mode.update(&mode, idx as usize);
|
||||
self.cursor
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_mode_info(render_state.mode.mode_info().cloned());
|
||||
self.cmd_line
|
||||
.set_mode_info(render_state.mode.mode_info().cloned());
|
||||
RepaintMode::Area(self.model.cur_point())
|
||||
}
|
||||
|
||||
@ -1328,10 +1328,25 @@ impl State {
|
||||
pub fn mode_info_set(
|
||||
&mut self,
|
||||
cursor_style_enabled: bool,
|
||||
mode_info: Vec<nvim::ModeInfo>,
|
||||
mode_infos: Vec<HashMap<String, Value>>,
|
||||
) -> RepaintMode {
|
||||
let mode_info_arr = mode_infos
|
||||
.iter()
|
||||
.map(|mode_info_map| mode::ModeInfo::new(mode_info_map))
|
||||
.collect();
|
||||
|
||||
match mode_info_arr {
|
||||
Ok(mode_info_arr) => {
|
||||
let mut render_state = self.render_state.borrow_mut();
|
||||
render_state.mode.set_info(cursor_style_enabled, mode_info);
|
||||
render_state
|
||||
.mode
|
||||
.set_info(cursor_style_enabled, mode_info_arr);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error load mode info: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user