summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Hakulinen <ville.hakulinen@gmail.com>2020-07-23 12:49:51 +0300
committerVille Hakulinen <ville.hakulinen@gmail.com>2020-07-23 12:49:51 +0300
commit2adccccd6b96c23a22d19c5bed8d17df681a4d4f (patch)
treeea9c97cf2d3c28770415a87d65da835f4be65822
parent675604525e5feb02f26ef962b2f6d95ea112b1f3 (diff)
Allow disabling the cursor movement animation
-rw-r--r--runtime/autoload/gnvim/cursor.vim10
-rw-r--r--runtime/doc/gnvim.txt3
-rw-r--r--src/nvim_bridge/mod.rs8
-rw-r--r--src/ui/grid/context.rs10
-rw-r--r--src/ui/grid/cursor.rs76
-rw-r--r--src/ui/grid/grid.rs15
-rw-r--r--src/ui/state.rs14
-rw-r--r--src/ui/ui.rs2
8 files changed, 112 insertions, 26 deletions
diff --git a/runtime/autoload/gnvim/cursor.vim b/runtime/autoload/gnvim/cursor.vim
new file mode 100644
index 0000000..caca879
--- /dev/null
+++ b/runtime/autoload/gnvim/cursor.vim
@@ -0,0 +1,10 @@
+command! -nargs=1 GnvimCursorEnableAnimations
+ \ call gnvim#cursor#enable_animations(<q-args>)
+
+function! gnvim#cursor#enable_animations(enable)
+ return rpcnotify(
+ \ g:gnvim_channel_id,
+ \ 'Gnvim',
+ \ 'EnableCursorAnimations',
+ \ a:enable == 1)
+endfunction
diff --git a/runtime/doc/gnvim.txt b/runtime/doc/gnvim.txt
index 1e61859..2e524be 100644
--- a/runtime/doc/gnvim.txt
+++ b/runtime/doc/gnvim.txt
@@ -55,6 +55,9 @@ Gnvim's cursor can be set to blink with `guicursor`.
Make cursor blink: `set guicursor+=a:blinkon333`
Make cursor not to blink: `set guicursor+=a:blinkon0`
+The cursor also has animated position movement, which is on by default. To
+disable it, use `GnvimCursorEnableAnimations 0` .
+
================================================================================
Commands *gnvim-commands*
diff --git a/src/nvim_bridge/mod.rs b/src/nvim_bridge/mod.rs
index 693d057..9a82571 100644
--- a/src/nvim_bridge/mod.rs
+++ b/src/nvim_bridge/mod.rs
@@ -976,6 +976,8 @@ pub enum GnvimEvent {
PopupmenuWidthDetails(u64),
PopupmenuShowMenuOnAllItems(bool),
+ EnableCursorAnimations(bool),
+
Unknown(String),
}
@@ -1261,6 +1263,12 @@ pub(crate) fn parse_gnvim_event(
GnvimEvent::PopupmenuShowMenuOnAllItems(b != 0)
}
+ "EnableCursorAnimations" => GnvimEvent::EnableCursorAnimations(
+ try_u64!(
+ args.get(1).ok_or("argument missing")?,
+ "failed to parse enable cursor animations argument"
+ ) == 1,
+ ),
_ => GnvimEvent::Unknown(String::from(cmd)),
};
diff --git a/src/ui/grid/context.rs b/src/ui/grid/context.rs
index 9709ead..d62ab1e 100644
--- a/src/ui/grid/context.rs
+++ b/src/ui/grid/context.rs
@@ -45,6 +45,7 @@ impl Context {
cols: usize,
rows: usize,
hl_defs: &HlDefs,
+ enable_cursor_animations: bool,
) -> Self {
let pango_context = da.get_pango_context().unwrap();
@@ -89,13 +90,18 @@ impl Context {
cairo::Context::new(&surface)
};
+ let cursor = Cursor {
+ disable_animation: !enable_cursor_animations,
+ ..Cursor::default()
+ };
+
Context {
cairo_context,
cell_metrics,
cell_metrics_update: None,
rows: vec![],
- cursor: Cursor::default(),
+ cursor,
cursor_context,
busy: false,
@@ -282,6 +288,8 @@ impl Context {
}
pub fn cell_at_cursor(&self) -> Option<&Cell> {
+ // TODO(ville): In some (all?) cases we want to get animation's target position if it
+ // differs from the current position.
self.cursor.pos.and_then(|pos| {
self.rows
.get(pos.0.ceil() as usize)
diff --git a/src/ui/grid/cursor.rs b/src/ui/grid/cursor.rs
index da1532b..3a3a5d4 100644
--- a/src/ui/grid/cursor.rs
+++ b/src/ui/grid/cursor.rs
@@ -1,7 +1,7 @@
use crate::ui::color::Color;
#[derive(Default)]
-struct Animation {
+pub struct Animation {
start: (f64, f64),
end: (f64, f64),
start_time: i64,
@@ -12,7 +12,9 @@ struct Animation {
pub struct Cursor {
/// Position, (row, col).
pub pos: Option<(f64, f64)>,
- animation: Animation,
+ /// Flag for disabling the movement animation.
+ pub disable_animation: bool,
+ pub animation: Option<Animation>,
/// Alpha color. Used to make the cursor blink.
pub alpha: f64,
@@ -26,17 +28,24 @@ pub struct Cursor {
impl Cursor {
pub fn goto(&mut self, row: f64, col: f64, frame_time: i64) {
+ // When we get our first cursor_goto, set the position directly.
if self.pos.is_none() {
self.pos = Some((row, col));
}
- let duration = 200;
- self.animation = Animation {
- start: self.pos.unwrap(),
- end: (row, col),
- start_time: frame_time,
- end_time: frame_time + 1000 * duration,
- };
+ // If cursor animation is disabled, set the position directly. Otherwise, set the animation
+ // so that we can animate cursor position change.
+ if self.disable_animation {
+ self.pos = Some((row, col));
+ } else {
+ let duration = 200;
+ self.animation = Some(Animation {
+ start: self.pos.unwrap(),
+ end: (row, col),
+ start_time: frame_time,
+ end_time: frame_time + 1000 * duration,
+ });
+ }
}
pub fn tick(&mut self, frame_time: i64) {
@@ -59,25 +68,27 @@ impl Cursor {
}
fn animate_position(&mut self, frame_time: i64) {
- let Animation {
+ if let Some(Animation {
start,
end,
start_time,
end_time,
- } = self.animation;
-
- let mut pos = self.pos.unwrap_or((0.0, 0.0));
-
- if frame_time < end_time && pos != end {
- let mut t = (frame_time - start_time) as f64
- / (end_time - start_time) as f64;
- t = ease_out_cubic(t);
- pos.0 = start.0 + t * (end.0 - start.0);
- pos.1 = start.1 + t * (end.1 - start.1);
-
- self.pos = Some(pos);
- } else if pos != end {
- self.pos = Some(end);
+ }) = self.animation
+ {
+ let mut pos = self.pos.unwrap_or((0.0, 0.0));
+
+ if frame_time < end_time && pos != end {
+ let mut t = (frame_time - start_time) as f64
+ / (end_time - start_time) as f64;
+ t = ease_out_cubic(t);
+ pos.0 = start.0 + t * (end.0 - start.0);
+ pos.1 = start.1 + t * (end.1 - start.1);
+
+ self.pos = Some(pos);
+ } else {
+ self.pos = Some(end);
+ self.animation = None;
+ }
}
}
}
@@ -139,4 +150,21 @@ mod tests {
cursor.tick(25000);
assert_eq!(cursor.pos, Some((13.349666797203126, 13.349666797203126)));
}
+
+ #[test]
+ fn test_animate_position_animation_disabled() {
+ let mut cursor = Cursor::default();
+ cursor.disable_animation = true;
+
+ // When we first set the position, it should be set immediately.
+ cursor.goto(15.0, 15.0, 1);
+ assert_eq!(cursor.pos, Some((15.0, 15.0)));
+
+ // Position animation is disabled, goto should change the position directly and tick
+ // shouldn't affect the position value at all.
+ cursor.goto(10.0, 10.0, 1);
+ assert_eq!(cursor.pos, Some((10.0, 10.0)));
+ cursor.tick(25000);
+ assert_eq!(cursor.pos, Some((10.0, 10.0)));
+ }
}
diff --git a/src/ui/grid/grid.rs b/src/ui/grid/grid.rs
index 77939ca..f470467 100644
--- a/src/ui/grid/grid.rs
+++ b/src/ui/grid/grid.rs
@@ -89,10 +89,18 @@ impl Grid {
cols: usize,
rows: usize,
hl_defs: &HlDefs,
+ enable_cursor_animations: bool,
) -> Self {
let da = DrawingArea::new();
let ctx = Rc::new(RefCell::new(Context::new(
- &da, win, font, line_space, cols, rows, hl_defs,
+ &da,
+ win,
+ font,
+ line_space,
+ cols,
+ rows,
+ hl_defs,
+ enable_cursor_animations,
)));
da.connect_draw(clone!(ctx => move |_, cr| {
@@ -461,6 +469,11 @@ impl Grid {
ctx.busy = busy;
}
+
+ pub fn enable_cursor_animations(&self, enable: bool) {
+ let mut ctx = self.context.borrow_mut();
+ ctx.cursor.disable_animation = !enable;
+ }
}
/// Handler for grid's drawingarea's draw event. Draws the internal cairo
diff --git a/src/ui/state.rs b/src/ui/state.rs
index dba0206..2374d4c 100644
--- a/src/ui/state.rs
+++ b/src/ui/state.rs
@@ -84,6 +84,8 @@ pub(crate) struct UIState {
pub font: Font,
pub line_space: i64,
+
+ pub enable_cursor_animations: bool,
}
impl UIState {
@@ -102,6 +104,7 @@ impl UIState {
Notify::GnvimEvent(event) => match event {
Ok(event) => self.handle_gnvim_event(&event, nvim),
Err(err) => {
+ error!("Failed to parse notify: {}", err);
let nvim = nvim.clone();
let msg = format!(
"echom \"Failed to parse gnvim notify: '{}'\"",
@@ -183,6 +186,7 @@ impl UIState {
e.width as usize,
e.height as usize,
&self.hl_defs,
+ self.enable_cursor_animations,
);
if let Some(ref mode) = self.current_mode {
@@ -714,6 +718,13 @@ impl UIState {
self.msg_window.set_pos(&grid, e.row as f64, h, e.scrolled);
}
+ fn enable_cursor_animations(&mut self, enable: bool) {
+ self.enable_cursor_animations = enable;
+ self.grids
+ .values()
+ .for_each(|g| g.enable_cursor_animations(enable));
+ }
+
fn handle_redraw_event(
&mut self,
window: &gtk::ApplicationWindow,
@@ -830,6 +841,9 @@ impl UIState {
GnvimEvent::PopupmenuShowMenuOnAllItems(should_show) => {
self.popupmenu.set_show_menu_on_all_items(*should_show);
}
+ GnvimEvent::EnableCursorAnimations(enable) => {
+ self.enable_cursor_animations(*enable);
+ }
GnvimEvent::Unknown(msg) => {
debug!("Received unknown GnvimEvent: {}", msg);
}
diff --git a/src/ui/ui.rs b/src/ui/ui.rs
index bf79cbb..fcf4258 100644
--- a/src/ui/ui.rs
+++ b/src/ui/ui.rs
@@ -87,6 +87,7 @@ impl UI {
80,
30,
&hl_defs,
+ true,
);
// Mark the default grid as active at the beginning.
grid.set_active(true);
@@ -242,6 +243,7 @@ impl UI {
font,
line_space,
current_mode: None,
+ enable_cursor_animations: true,
})),
nvim,
}