From 354bfce670f53aaedd948ccaa3a9cb019dfaa029 Mon Sep 17 00:00:00 2001 From: daa Date: Sun, 1 Apr 2018 17:29:05 +0300 Subject: [PATCH] Support for blinkwait gui cursor setting --- src/cmd_line.rs | 16 ++++++--- src/cursor.rs | 44 +++++++++++++++--------- src/mode.rs | 69 +++++++++++++++++++++++++++++++++++--- src/nvim/mod.rs | 2 -- src/nvim/mode_info.rs | 66 ------------------------------------ src/nvim/redraw_handler.rs | 16 ++------- src/render/mod.rs | 3 -- src/shell.rs | 35 +++++++++++++------ 8 files changed, 132 insertions(+), 119 deletions(-) delete mode 100644 src/nvim/mode_info.rs diff --git a/src/cmd_line.rs b/src/cmd_line.rs index 6ab4bc2..dcdf9f2 100644 --- a/src/cmd_line.rs +++ b/src/cmd_line.rs @@ -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) { + self.state + .borrow_mut() + .cursor + .as_mut() + .unwrap() + .set_mode_info(mode_info); + } } fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> Inhibit { @@ -419,7 +429,6 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> 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>) -> Inhibit { &render_state.font_ctx, &level.model_layout.model, &render_state.color_model, - &render_state.mode, ); } Inhibit(false) diff --git a/src/cursor.rs b/src/cursor.rs index 8c5068b..5714306 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -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, @@ -85,7 +83,7 @@ pub struct EmptyCursor; impl EmptyCursor { pub fn new() -> Self { - EmptyCursor { } + EmptyCursor {} } } @@ -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 { state: Arc>>, + mode_info: Option, } impl BlinkCursor { pub fn new(redraw_cb: Weak>) -> Self { BlinkCursor { state: Arc::new(UiMutex::new(State::new(redraw_cb))), + mode_info: None, } } + pub fn set_mode_info(&mut self, mode_info: Option) { + 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 Cursor for BlinkCursor { &self, ctx: &cairo::Context, font_ctx: &render::Context, - mode: &mode::Mode, line_y: f64, double_width: bool, bg: &Color, @@ -166,7 +176,12 @@ impl Cursor for BlinkCursor { 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 Cursor for BlinkCursor { } 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(state: &Arc>>) -> 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))); diff --git a/src/mode.rs b/src/mode.rs index 8d58dcc..456bec5 100644 --- a/src/mode.rs +++ b/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>, + info: Option>, } 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) { + pub fn set_info(&mut self, cursor_style_enabled: bool, info: Vec) { 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 { + 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, + cell_percentage: Option, + pub blinkwait: Option, +} + +impl ModeInfo { + pub fn new(mode_info_map: &HashMap) -> Result { + 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) + } +} diff --git a/src/nvim/mod.rs b/src/nvim/mod.rs index 5ec8c92..bda9ae0 100644 --- a/src/nvim/mod.rs +++ b/src/nvim/mod.rs @@ -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; diff --git a/src/nvim/mode_info.rs b/src/nvim/mode_info.rs deleted file mode 100644 index 7515d7e..0000000 --- a/src/nvim/mode_info.rs +++ /dev/null @@ -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 { - 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, - cell_percentage: Option, -} - -impl ModeInfo { - pub fn new(mode_info_arr: &Vec<(Value, Value)>) -> Result { - 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) - } -} diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index 865f91b..5258cb4 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -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) { let mut show_popup_finded = false; diff --git a/src/render/mod.rs b/src/render/mod.rs index 60ce02e..de74b38 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -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( 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( cursor.draw( ctx, font_ctx, - mode, line_y, double_width, color_model.actual_cell_bg(cell), diff --git a/src/shell.rs b/src/shell.rs index 660ed18..c4971ba 100644 --- a/src/shell.rs +++ b/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, + mode_infos: Vec>, ) -> RepaintMode { - let mut render_state = self.render_state.borrow_mut(); - render_state.mode.set_info(cursor_style_enabled, mode_info); + 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_arr); + } + Err(err) => { + error!("Error load mode info: {}", err); + } + } + RepaintMode::Nothing }