Support for blinkwait gui cursor setting

This commit is contained in:
daa 2018-04-01 17:29:05 +03:00
parent 83ca7bf342
commit 354bfce670
8 changed files with 132 additions and 119 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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