Move out resize/init code from draw handler
This commit is contained in:
parent
dc8d6d5a70
commit
94747615af
203
src/nvim.rs
203
src/nvim.rs
@ -47,26 +47,29 @@ pub trait RedrawEvents {
|
||||
|
||||
fn on_busy(&mut self, busy: bool) -> RepaintMode;
|
||||
|
||||
fn popupmenu_show(&mut self,
|
||||
menu: &[Vec<&str>],
|
||||
selected: i64,
|
||||
row: u64,
|
||||
col: u64)
|
||||
-> RepaintMode;
|
||||
fn popupmenu_show(
|
||||
&mut self,
|
||||
menu: &[Vec<&str>],
|
||||
selected: i64,
|
||||
row: u64,
|
||||
col: u64,
|
||||
) -> RepaintMode;
|
||||
|
||||
fn popupmenu_hide(&mut self) -> RepaintMode;
|
||||
|
||||
fn popupmenu_select(&mut self, selected: i64) -> RepaintMode;
|
||||
|
||||
fn tabline_update(&mut self,
|
||||
selected: Tabpage,
|
||||
tabs: Vec<(Tabpage, Option<String>)>)
|
||||
-> RepaintMode;
|
||||
fn tabline_update(
|
||||
&mut self,
|
||||
selected: Tabpage,
|
||||
tabs: Vec<(Tabpage, Option<String>)>,
|
||||
) -> RepaintMode;
|
||||
|
||||
fn mode_info_set(&mut self,
|
||||
cursor_style_enabled: bool,
|
||||
mode_info: Vec<ModeInfo>)
|
||||
-> RepaintMode;
|
||||
fn mode_info_set(
|
||||
&mut self,
|
||||
cursor_style_enabled: bool,
|
||||
mode_info: Vec<ModeInfo>,
|
||||
) -> RepaintMode;
|
||||
}
|
||||
|
||||
pub trait GuiApi {
|
||||
@ -116,19 +119,19 @@ pub enum CursorShape {
|
||||
|
||||
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())?;
|
||||
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
|
||||
}
|
||||
})
|
||||
"block" => CursorShape::Block,
|
||||
"horizontal" => CursorShape::Horizontal,
|
||||
"vertical" => CursorShape::Vertical,
|
||||
_ => {
|
||||
error!("Unknown cursor_shape {}", str_code);
|
||||
CursorShape::Unknown
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,9 +158,9 @@ impl ModeInfo {
|
||||
};
|
||||
|
||||
Ok(ModeInfo {
|
||||
cursor_shape,
|
||||
cell_percentage,
|
||||
})
|
||||
cursor_shape,
|
||||
cell_percentage,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cursor_shape(&self) -> Option<&CursorShape> {
|
||||
@ -177,7 +180,8 @@ pub struct NvimInitError {
|
||||
|
||||
impl NvimInitError {
|
||||
pub fn new_post_init<E>(error: E) -> NvimInitError
|
||||
where E: Into<Box<error::Error>>
|
||||
where
|
||||
E: Into<Box<error::Error>>,
|
||||
{
|
||||
NvimInitError {
|
||||
cmd: None,
|
||||
@ -186,7 +190,8 @@ impl NvimInitError {
|
||||
}
|
||||
|
||||
pub fn new<E>(cmd: &Command, error: E) -> NvimInitError
|
||||
where E: Into<Box<error::Error>>
|
||||
where
|
||||
E: Into<Box<error::Error>>,
|
||||
{
|
||||
NvimInitError {
|
||||
cmd: Some(format!("{:?}", cmd)),
|
||||
@ -219,9 +224,10 @@ impl error::Error for NvimInitError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(shell: Arc<UiMutex<shell::State>>,
|
||||
nvim_bin_path: Option<&String>)
|
||||
-> result::Result<Neovim, NvimInitError> {
|
||||
pub fn start(
|
||||
shell: Arc<UiMutex<shell::State>>,
|
||||
nvim_bin_path: Option<&String>,
|
||||
) -> result::Result<Neovim, NvimInitError> {
|
||||
let mut cmd = if let Some(path) = nvim_bin_path {
|
||||
Command::new(path)
|
||||
} else {
|
||||
@ -237,11 +243,14 @@ pub fn start(shell: Arc<UiMutex<shell::State>>,
|
||||
.stderr(Stdio::inherit());
|
||||
|
||||
if let Ok(runtime_path) = env::var("NVIM_GTK_RUNTIME_PATH") {
|
||||
cmd.arg("--cmd")
|
||||
.arg(format!("let &rtp.=',{}'", runtime_path));
|
||||
cmd.arg("--cmd").arg(
|
||||
format!("let &rtp.=',{}'", runtime_path),
|
||||
);
|
||||
} else if let Some(prefix) = option_env!("PREFIX") {
|
||||
cmd.arg("--cmd")
|
||||
.arg(format!("let &rtp.=',{}/share/nvim-gtk/runtime'", prefix));
|
||||
cmd.arg("--cmd").arg(format!(
|
||||
"let &rtp.=',{}/share/nvim-gtk/runtime'",
|
||||
prefix
|
||||
));
|
||||
} else {
|
||||
cmd.arg("--cmd").arg("let &rtp.=',runtime'");
|
||||
}
|
||||
@ -255,28 +264,33 @@ pub fn start(shell: Arc<UiMutex<shell::State>>,
|
||||
|
||||
let mut nvim = Neovim::new(session);
|
||||
|
||||
nvim.session
|
||||
.start_event_loop_handler(NvimHandler::new(shell));
|
||||
nvim.session.start_event_loop_handler(
|
||||
NvimHandler::new(shell),
|
||||
);
|
||||
|
||||
Ok(nvim)
|
||||
}
|
||||
|
||||
pub fn post_start_init(nvim: &mut Neovim,
|
||||
open_path: Option<&String>,
|
||||
cols: u64,
|
||||
rows: u64)
|
||||
-> result::Result<(), NvimInitError> {
|
||||
pub fn post_start_init(
|
||||
nvim: &mut Neovim,
|
||||
open_path: Option<&String>,
|
||||
cols: u64,
|
||||
rows: u64,
|
||||
) -> result::Result<(), NvimInitError> {
|
||||
let mut opts = UiAttachOptions::new();
|
||||
opts.set_popupmenu_external(false);
|
||||
opts.set_tabline_external(true);
|
||||
nvim.ui_attach(cols, rows, opts)
|
||||
.map_err(NvimInitError::new_post_init)?;
|
||||
nvim.command("runtime! ginit.vim")
|
||||
.map_err(NvimInitError::new_post_init)?;
|
||||
nvim.ui_attach(cols, rows, opts).map_err(
|
||||
NvimInitError::new_post_init,
|
||||
)?;
|
||||
nvim.command("runtime! ginit.vim").map_err(
|
||||
NvimInitError::new_post_init,
|
||||
)?;
|
||||
|
||||
if let Some(path) = open_path {
|
||||
nvim.command(&format!("e {}", path))
|
||||
.map_err(NvimInitError::new_post_init)?;
|
||||
nvim.command(&format!("e {}", path)).map_err(
|
||||
NvimInitError::new_post_init,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -325,10 +339,10 @@ impl NvimHandler {
|
||||
if let Some(ev_name) = params[0].as_str().map(String::from) {
|
||||
let args = params.iter().skip(1).cloned().collect();
|
||||
self.safe_call(move |ui| {
|
||||
call_gui_event(ui, &ev_name, &args)?;
|
||||
ui.on_redraw(&RepaintMode::All);
|
||||
Ok(())
|
||||
});
|
||||
call_gui_event(ui, &ev_name, &args)?;
|
||||
ui.on_redraw(&RepaintMode::All);
|
||||
Ok(())
|
||||
});
|
||||
} else {
|
||||
println!("Unsupported event {:?}", params);
|
||||
}
|
||||
@ -343,15 +357,16 @@ impl NvimHandler {
|
||||
}
|
||||
|
||||
fn safe_call<F>(&self, cb: F)
|
||||
where F: Fn(&mut shell::State) -> result::Result<(), String> + 'static + Send
|
||||
where
|
||||
F: Fn(&mut shell::State) -> result::Result<(), String> + 'static + Send,
|
||||
{
|
||||
let shell = self.shell.clone();
|
||||
glib::idle_add(move || {
|
||||
if let Err(msg) = cb(&mut shell.borrow_mut()) {
|
||||
println!("Error call function: {}", msg);
|
||||
}
|
||||
glib::Continue(false)
|
||||
});
|
||||
if let Err(msg) = cb(&mut shell.borrow_mut()) {
|
||||
println!("Error call function: {}", msg);
|
||||
}
|
||||
glib::Continue(false)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,21 +377,24 @@ impl Handler for NvimHandler {
|
||||
}
|
||||
|
||||
|
||||
fn call_gui_event(ui: &mut shell::State,
|
||||
method: &str,
|
||||
args: &Vec<Value>)
|
||||
-> result::Result<(), String> {
|
||||
fn call_gui_event(
|
||||
ui: &mut shell::State,
|
||||
method: &str,
|
||||
args: &Vec<Value>,
|
||||
) -> result::Result<(), String> {
|
||||
match method {
|
||||
"Font" => ui.set_font(try_str!(args[0])),
|
||||
"Option" => {
|
||||
match try_str!(args[0]) {
|
||||
"Popupmenu" => {
|
||||
ui.nvim()
|
||||
.unwrap()
|
||||
.set_option(UiOption::ExtPopupmenu(try_uint!(args[1]) == 1))
|
||||
.map_err(|e| e.to_string())?
|
||||
}
|
||||
"Tabline" => {
|
||||
ui.nvim()
|
||||
.unwrap()
|
||||
.set_option(UiOption::ExtTabline(try_uint!(args[1]) == 1))
|
||||
.map_err(|e| e.to_string())?
|
||||
}
|
||||
@ -388,10 +406,11 @@ fn call_gui_event(ui: &mut shell::State,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call(ui: &mut shell::State,
|
||||
method: &str,
|
||||
args: &[Value])
|
||||
-> result::Result<RepaintMode, String> {
|
||||
fn call(
|
||||
ui: &mut shell::State,
|
||||
method: &str,
|
||||
args: &[Value],
|
||||
) -> result::Result<RepaintMode, String> {
|
||||
let repaint_mode = match method {
|
||||
"cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])),
|
||||
"put" => ui.on_put(try_str!(args[0])),
|
||||
@ -407,10 +426,12 @@ fn call(ui: &mut shell::State,
|
||||
}
|
||||
"eol_clear" => ui.on_eol_clear(),
|
||||
"set_scroll_region" => {
|
||||
ui.on_set_scroll_region(try_uint!(args[0]),
|
||||
try_uint!(args[1]),
|
||||
try_uint!(args[2]),
|
||||
try_uint!(args[3]));
|
||||
ui.on_set_scroll_region(
|
||||
try_uint!(args[0]),
|
||||
try_uint!(args[1]),
|
||||
try_uint!(args[2]),
|
||||
try_uint!(args[3]),
|
||||
);
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
"scroll" => ui.on_scroll(try_int!(args[0])),
|
||||
@ -424,15 +445,17 @@ fn call(ui: &mut shell::State,
|
||||
"busy_stop" => ui.on_busy(false),
|
||||
"popupmenu_show" => {
|
||||
let menu_items = map_array!(args[0], "Error get menu list array", |item| {
|
||||
map_array!(item,
|
||||
"Error get menu item array",
|
||||
|col| col.as_str().ok_or("Error get menu column"))
|
||||
map_array!(item, "Error get menu item array", |col| {
|
||||
col.as_str().ok_or("Error get menu column")
|
||||
})
|
||||
})?;
|
||||
|
||||
ui.popupmenu_show(&menu_items,
|
||||
try_int!(args[1]),
|
||||
try_uint!(args[2]),
|
||||
try_uint!(args[3]))
|
||||
ui.popupmenu_show(
|
||||
&menu_items,
|
||||
try_int!(args[1]),
|
||||
try_uint!(args[2]),
|
||||
try_uint!(args[3]),
|
||||
)
|
||||
}
|
||||
"popupmenu_hide" => ui.popupmenu_hide(),
|
||||
"popupmenu_select" => ui.popupmenu_select(try_int!(args[0])),
|
||||
@ -442,9 +465,9 @@ fn call(ui: &mut shell::State,
|
||||
.ok_or_else(|| "Error get map for tab".to_owned())
|
||||
.and_then(|tab_map| tab_map.to_attrs_map())
|
||||
.map(|tab_attrs| {
|
||||
let name_attr = tab_attrs
|
||||
.get("name")
|
||||
.and_then(|n| n.as_str().map(|s| s.to_owned()));
|
||||
let name_attr = tab_attrs.get("name").and_then(
|
||||
|n| n.as_str().map(|s| s.to_owned()),
|
||||
);
|
||||
let tab_attr = tab_attrs
|
||||
.get("tab")
|
||||
.map(|tab_id| Tabpage::new(tab_id.clone()))
|
||||
@ -456,13 +479,15 @@ fn call(ui: &mut shell::State,
|
||||
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))
|
||||
})?;
|
||||
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)
|
||||
}
|
||||
_ => {
|
||||
|
@ -245,15 +245,17 @@ impl Projects {
|
||||
fn load_oldfiles(&mut self) {
|
||||
let shell_borrow = self.shell.borrow();
|
||||
let shell_state = shell_borrow.state.borrow_mut();
|
||||
let mut nvim = shell_state.nvim();
|
||||
|
||||
let store = EntryStore::load(&mut nvim);
|
||||
store.populate(&self.get_list_store(), None);
|
||||
self.store = Some(store);
|
||||
let nvim = shell_state.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
let store = EntryStore::load(&mut nvim);
|
||||
store.populate(&self.get_list_store(), None);
|
||||
self.store = Some(store);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.store.take().unwrap().save();
|
||||
self.store.take().map(|s| s.save());
|
||||
self.get_list_store().clear();
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,5 @@ fn monospace_font_changed(mut shell: &mut Shell, state: &mut State) {
|
||||
// rpc is priority for font
|
||||
if state.font_source != FontSource::Rpc {
|
||||
state.update_font(&mut shell);
|
||||
shell.redraw(&RepaintMode::All);
|
||||
}
|
||||
}
|
||||
|
228
src/shell.rs
228
src/shell.rs
@ -48,6 +48,12 @@ macro_rules! idle_cb_call {
|
||||
)
|
||||
}
|
||||
|
||||
enum ResizeState {
|
||||
RequestNvimResize(glib::SourceId),
|
||||
RequestWindowResize,
|
||||
Wait,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
pub model: UiModel,
|
||||
color_model: ColorModel,
|
||||
@ -67,9 +73,7 @@ pub struct State {
|
||||
im_context: gtk::IMMulticontext,
|
||||
error_area: error::ErrorArea,
|
||||
|
||||
request_resize: bool,
|
||||
request_nvim_resize: bool,
|
||||
resize_timer: Option<glib::SourceId>,
|
||||
resize_state: ResizeState,
|
||||
|
||||
options: ShellOptions,
|
||||
|
||||
@ -102,9 +106,7 @@ impl State {
|
||||
im_context: gtk::IMMulticontext::new(),
|
||||
error_area: error::ErrorArea::new(),
|
||||
|
||||
resize_timer: None,
|
||||
request_resize: false,
|
||||
request_nvim_resize: false,
|
||||
resize_state: ResizeState::Wait,
|
||||
|
||||
options,
|
||||
|
||||
@ -120,8 +122,12 @@ impl State {
|
||||
&self.color_model.bg_color
|
||||
}
|
||||
|
||||
pub fn nvim(&self) -> RefMut<Neovim> {
|
||||
RefMut::map(self.nvim.borrow_mut(), |n| n.nvim_mut())
|
||||
pub fn nvim(&self) -> Option<RefMut<Neovim>> {
|
||||
if self.nvim.borrow().is_initialized() {
|
||||
Some(RefMut::map(self.nvim.borrow_mut(), |n| n.nvim_mut()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nvim_clone(&self) -> Rc<RefCell<NeovimClient>> {
|
||||
@ -151,37 +157,36 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn open_file(&self, path: &str) {
|
||||
let mut nvim = self.nvim();
|
||||
nvim.command(&format!("e {}", path)).report_err(&mut *nvim);
|
||||
if let Some(mut nvim) = self.nvim() {
|
||||
nvim.command(&format!("e {}", path)).report_err(&mut *nvim);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cd(&self, path: &str) {
|
||||
let mut nvim = self.nvim();
|
||||
nvim.command(&format!("cd {}", path)).report_err(&mut *nvim);
|
||||
}
|
||||
|
||||
fn request_resize(&mut self) {
|
||||
self.request_resize = true;
|
||||
}
|
||||
|
||||
fn request_nvim_resize(&mut self) {
|
||||
self.request_nvim_resize = true;
|
||||
if let Some(mut nvim) = self.nvim() {
|
||||
nvim.command(&format!("cd {}", path)).report_err(&mut *nvim);
|
||||
}
|
||||
}
|
||||
|
||||
fn close_popup_menu(&self) {
|
||||
if self.popup_menu.borrow().is_open() {
|
||||
let mut nvim = self.nvim();
|
||||
nvim.input("<Esc>").report_err(&mut *nvim);
|
||||
if let Some(mut nvim) = self.nvim() {
|
||||
nvim.input("<Esc>").report_err(&mut *nvim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_draw_area<M: AsRef<ModelRect>>(&mut self, rect_list: &[M]) {
|
||||
// extends by items before, then after changes
|
||||
|
||||
let rects: Vec<_> = rect_list.iter().map(|rect| rect.as_ref().clone()).map(|mut rect| {
|
||||
rect.extend_by_items(&self.model);
|
||||
rect
|
||||
}).collect();
|
||||
let rects: Vec<_> = rect_list
|
||||
.iter()
|
||||
.map(|rect| rect.as_ref().clone())
|
||||
.map(|mut rect| {
|
||||
rect.extend_by_items(&self.model);
|
||||
rect
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.update_dirty_glyphs();
|
||||
|
||||
@ -239,6 +244,38 @@ impl State {
|
||||
|
||||
self.im_context.reset();
|
||||
}
|
||||
|
||||
fn resize_main_window(&mut self) {
|
||||
match self.resize_state {
|
||||
ResizeState::RequestNvimResize(_) => return,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let &CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
..
|
||||
} = self.font_ctx.cell_metrics();
|
||||
|
||||
let width = self.drawing_area.get_allocated_width();
|
||||
let height = self.drawing_area.get_allocated_height();
|
||||
let request_height = (self.model.rows as f64 * line_height) as i32;
|
||||
let request_width = (self.model.columns as f64 * char_width) as i32;
|
||||
|
||||
if width != request_width || height != request_height {
|
||||
self.resize_state = ResizeState::RequestWindowResize;
|
||||
|
||||
let window: gtk::Window = self.drawing_area
|
||||
.get_toplevel()
|
||||
.unwrap()
|
||||
.downcast()
|
||||
.unwrap();
|
||||
let (win_width, win_height) = window.get_size();
|
||||
let h_border = win_width - width;
|
||||
let v_border = win_height - height;
|
||||
window.resize(request_width + h_border, request_height + v_border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UiState {
|
||||
@ -419,11 +456,12 @@ impl Shell {
|
||||
try_nvim_resize(&ref_state);
|
||||
false
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn redraw(&self, mode: &RepaintMode) {
|
||||
self.state.borrow_mut().on_redraw(mode);
|
||||
let ref_state = self.state.clone();
|
||||
state.drawing_area.connect_size_allocate(
|
||||
move |_, _| init_nvim(&ref_state),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
@ -445,7 +483,11 @@ impl Shell {
|
||||
|
||||
pub fn detach_ui(&mut self) {
|
||||
let state = self.state.borrow();
|
||||
state.nvim().ui_detach().expect("Error in ui_detach");
|
||||
|
||||
let nvim = state.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
nvim.ui_detach().expect("Error in ui_detach");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_paste(&self) {
|
||||
@ -456,14 +498,19 @@ impl Shell {
|
||||
"<Esc>\"*pa"
|
||||
};
|
||||
|
||||
let mut nvim = state.nvim();
|
||||
nvim.input(paste_command).report_err(&mut *nvim);
|
||||
let nvim = state.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
nvim.input(paste_command).report_err(&mut *nvim);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_save_all(&self) {
|
||||
let state = self.state.borrow();
|
||||
let nvim = &mut *state.nvim();
|
||||
nvim.command(":wa").report_err(nvim);
|
||||
|
||||
let nvim = state.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
nvim.command(":wa").report_err(&mut *nvim);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_detach_cb<F>(&self, cb: Option<F>)
|
||||
@ -544,14 +591,17 @@ fn mouse_input(shell: &mut State, input: &str, state: ModifierType, position: (f
|
||||
char_width,
|
||||
..
|
||||
} = shell.font_ctx.cell_metrics();
|
||||
let mut nvim = shell.nvim();
|
||||
let (x, y) = position;
|
||||
let col = (x / char_width).trunc() as u64;
|
||||
let row = (y / line_height).trunc() as u64;
|
||||
let input_str = format!("{}<{},{}>", keyval_to_input_string(input, state), col, row);
|
||||
nvim.input(&input_str).expect(
|
||||
"Can't send mouse input event",
|
||||
);
|
||||
|
||||
let nvim = shell.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
nvim.input(&input_str).expect(
|
||||
"Can't send mouse input event",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn gtk_button_release(ui_state: &mut UiState) -> Inhibit {
|
||||
@ -567,15 +617,9 @@ fn gtk_motion_notify(shell: &mut State, ui_state: &mut UiState, ev: &EventMotion
|
||||
}
|
||||
|
||||
fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
|
||||
if state_arc.borrow_mut().request_nvim_resize {
|
||||
try_nvim_resize(state_arc);
|
||||
}
|
||||
|
||||
init_nvim(state_arc);
|
||||
|
||||
let mut state = state_arc.borrow_mut();
|
||||
let state = state_arc.borrow();
|
||||
if state.nvim.borrow().is_initialized() {
|
||||
request_window_resize(&mut *state);
|
||||
render::render(
|
||||
ctx,
|
||||
state.cursor.as_ref().unwrap(),
|
||||
@ -664,21 +708,6 @@ fn init_nvim_async(
|
||||
});
|
||||
}
|
||||
|
||||
fn init_nvim(state_arc: &Arc<UiMutex<State>>) {
|
||||
let state = state_arc.borrow();
|
||||
|
||||
let mut nvim = state.nvim.borrow_mut();
|
||||
if nvim.is_uninitialized() {
|
||||
nvim.set_in_progress();
|
||||
|
||||
let (cols, rows) = state.calc_nvim_size();
|
||||
|
||||
let state_arc = state_arc.clone();
|
||||
let options = state.options.clone();
|
||||
thread::spawn(move || init_nvim_async(state_arc, options, cols, rows));
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
||||
let layout = ctx.create_pango_layout();
|
||||
let desc = state.get_font_desc();
|
||||
@ -719,47 +748,32 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
|
||||
);
|
||||
}
|
||||
|
||||
fn request_window_resize(state: &mut State) {
|
||||
if !state.request_resize {
|
||||
return;
|
||||
}
|
||||
if state.resize_timer.is_some() {
|
||||
return;
|
||||
}
|
||||
fn init_nvim(state_ref: &Arc<UiMutex<State>>) {
|
||||
let state = state_ref.borrow();
|
||||
let mut nvim = state.nvim.borrow_mut();
|
||||
if nvim.is_uninitialized() {
|
||||
nvim.set_in_progress();
|
||||
|
||||
let &CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
..
|
||||
} = state.font_ctx.cell_metrics();
|
||||
state.request_resize = false;
|
||||
let (cols, rows) = state.calc_nvim_size();
|
||||
|
||||
let width = state.drawing_area.get_allocated_width();
|
||||
let height = state.drawing_area.get_allocated_height();
|
||||
let request_height = (state.model.rows as f64 * line_height) as i32;
|
||||
let request_width = (state.model.columns as f64 * char_width) as i32;
|
||||
|
||||
if width != request_width || height != request_height {
|
||||
let window: gtk::Window = state
|
||||
.drawing_area
|
||||
.get_toplevel()
|
||||
.unwrap()
|
||||
.downcast()
|
||||
.unwrap();
|
||||
let (win_width, win_height) = window.get_size();
|
||||
let h_border = win_width - width;
|
||||
let v_border = win_height - height;
|
||||
window.resize(request_width + h_border, request_height + v_border);
|
||||
let state_arc = state_ref.clone();
|
||||
let options = state.options.clone();
|
||||
thread::spawn(move || init_nvim_async(state_arc, options, cols, rows));
|
||||
}
|
||||
}
|
||||
|
||||
fn try_nvim_resize(state: &Arc<UiMutex<State>>) {
|
||||
let mut state_ref = state.borrow_mut();
|
||||
|
||||
state_ref.request_nvim_resize = false;
|
||||
|
||||
if let Some(timer) = state_ref.resize_timer {
|
||||
glib::source_remove(timer);
|
||||
match state_ref.resize_state {
|
||||
ResizeState::RequestWindowResize => {
|
||||
state_ref.resize_state = ResizeState::Wait;
|
||||
return;
|
||||
}
|
||||
ResizeState::RequestNvimResize(timer) => {
|
||||
glib::source_remove(timer);
|
||||
}
|
||||
ResizeState::Wait => (),
|
||||
}
|
||||
|
||||
if !state_ref.nvim.borrow().is_initialized() {
|
||||
@ -768,14 +782,17 @@ fn try_nvim_resize(state: &Arc<UiMutex<State>>) {
|
||||
|
||||
let (columns, rows) = state_ref.calc_nvim_size();
|
||||
let state = state.clone();
|
||||
state_ref.resize_timer = Some(glib::timeout_add(250, move || {
|
||||
state_ref.resize_state = ResizeState::RequestNvimResize(gtk::timeout_add(250, move || {
|
||||
let mut state_ref = state.borrow_mut();
|
||||
|
||||
state_ref.resize_timer = None;
|
||||
state_ref.resize_state = ResizeState::Wait;
|
||||
|
||||
if state_ref.model.rows != rows || state_ref.model.columns != columns {
|
||||
if let Err(err) = state_ref.nvim().ui_try_resize(columns as u64, rows as u64) {
|
||||
error!("Error trying resize nvim {}", err);
|
||||
let nvim = state_ref.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
if let Err(err) = nvim.ui_try_resize(columns as u64, rows as u64) {
|
||||
error!("Error trying resize nvim {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Continue(false)
|
||||
@ -804,7 +821,8 @@ impl RedrawEvents for State {
|
||||
|
||||
fn on_resize(&mut self, columns: u64, rows: u64) -> RepaintMode {
|
||||
self.model = UiModel::new(rows, columns);
|
||||
self.request_resize();
|
||||
self.resize_main_window();
|
||||
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
@ -813,7 +831,7 @@ impl RedrawEvents for State {
|
||||
RepaintMode::All => {
|
||||
self.update_dirty_glyphs();
|
||||
self.drawing_area.queue_draw();
|
||||
},
|
||||
}
|
||||
RepaintMode::Area(ref rect) => self.queue_draw_area(&[rect]),
|
||||
RepaintMode::AreaList(ref list) => self.queue_draw_area(&list.list),
|
||||
RepaintMode::Nothing => (),
|
||||
@ -968,10 +986,12 @@ impl RedrawEvents for State {
|
||||
|
||||
impl GuiApi for State {
|
||||
fn set_font(&mut self, font_desc: &str) {
|
||||
self.set_font_desc(font_desc);
|
||||
self.request_nvim_resize();
|
||||
{
|
||||
let mut settings = self.settings.borrow_mut();
|
||||
settings.set_font_source(FontSource::Rpc);
|
||||
}
|
||||
|
||||
let mut settings = self.settings.borrow_mut();
|
||||
settings.set_font_source(FontSource::Rpc);
|
||||
self.set_font_desc(font_desc);
|
||||
self.resize_main_window();
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,7 @@ pub fn can_close_window(comps: &UiMutex<Components>, shell: &RefCell<Shell>) ->
|
||||
}
|
||||
}
|
||||
|
||||
fn show_not_saved_dlg(comps: &UiMutex<Components>,
|
||||
shell: &Shell,
|
||||
changed_bufs: &[String])
|
||||
-> bool {
|
||||
fn show_not_saved_dlg(comps: &UiMutex<Components>, shell: &Shell, changed_bufs: &[String]) -> bool {
|
||||
let mut changed_files = changed_bufs
|
||||
.iter()
|
||||
.map(|n| if n.is_empty() { "<No name>" } else { n })
|
||||
@ -35,24 +32,30 @@ fn show_not_saved_dlg(comps: &UiMutex<Components>,
|
||||
changed_files.pop();
|
||||
|
||||
let flags = gtk::DIALOG_MODAL | gtk::DIALOG_DESTROY_WITH_PARENT;
|
||||
let dlg = MessageDialog::new(Some(comps.borrow().window()),
|
||||
flags,
|
||||
MessageType::Question,
|
||||
ButtonsType::None,
|
||||
&format!("Save changes to '{}'?", changed_files));
|
||||
let dlg = MessageDialog::new(
|
||||
Some(comps.borrow().window()),
|
||||
flags,
|
||||
MessageType::Question,
|
||||
ButtonsType::None,
|
||||
&format!("Save changes to '{}'?", changed_files),
|
||||
);
|
||||
|
||||
const SAVE_ID: i32 = 0;
|
||||
const CLOSE_WITHOUT_SAVE: i32 = 1;
|
||||
const CANCEL_ID: i32 = 2;
|
||||
|
||||
dlg.add_buttons(&[("_Yes", SAVE_ID),
|
||||
("_No", CLOSE_WITHOUT_SAVE),
|
||||
("_Cancel", CANCEL_ID)]);
|
||||
dlg.add_buttons(
|
||||
&[
|
||||
("_Yes", SAVE_ID),
|
||||
("_No", CLOSE_WITHOUT_SAVE),
|
||||
("_Cancel", CANCEL_ID),
|
||||
],
|
||||
);
|
||||
|
||||
let res = match dlg.run() {
|
||||
SAVE_ID => {
|
||||
let state = shell.state.borrow();
|
||||
let mut nvim = state.nvim();
|
||||
let mut nvim = state.nvim().unwrap();
|
||||
match nvim.command("wa") {
|
||||
Err(ref err) => {
|
||||
println!("Error: {}", err);
|
||||
@ -72,32 +75,46 @@ fn show_not_saved_dlg(comps: &UiMutex<Components>,
|
||||
|
||||
fn get_changed_buffers(shell: &Shell) -> Result<Vec<String>, CallError> {
|
||||
let state = shell.state.borrow();
|
||||
let mut nvim = state.nvim();
|
||||
let buffers = nvim.list_bufs().unwrap();
|
||||
let nvim = state.nvim();
|
||||
if let Some(mut nvim) = nvim {
|
||||
let buffers = nvim.list_bufs().unwrap();
|
||||
|
||||
Ok(buffers
|
||||
.iter()
|
||||
.map(|buf| {
|
||||
(match buf.get_option(&mut nvim, "modified") {
|
||||
Ok(Value::Boolean(val)) => val,
|
||||
Ok(_) => {
|
||||
println!("Value must be boolean");
|
||||
false
|
||||
}
|
||||
Err(ref err) => {
|
||||
println!("Something going wrong while getting buffer option: {}", err);
|
||||
false
|
||||
}
|
||||
},
|
||||
match buf.get_name(&mut nvim) {
|
||||
Ok(name) => name,
|
||||
Err(ref err) => {
|
||||
println!("Something going wrong while getting buffer name: {}", err);
|
||||
"<Error>".to_owned()
|
||||
}
|
||||
})
|
||||
})
|
||||
.filter(|e| e.0)
|
||||
.map(|e| e.1)
|
||||
.collect())
|
||||
Ok(
|
||||
buffers
|
||||
.iter()
|
||||
.map(|buf| {
|
||||
(
|
||||
match buf.get_option(&mut nvim, "modified") {
|
||||
Ok(Value::Boolean(val)) => val,
|
||||
Ok(_) => {
|
||||
println!("Value must be boolean");
|
||||
false
|
||||
}
|
||||
Err(ref err) => {
|
||||
println!(
|
||||
"Something going wrong while getting buffer option: {}",
|
||||
err
|
||||
);
|
||||
false
|
||||
}
|
||||
},
|
||||
match buf.get_name(&mut nvim) {
|
||||
Ok(name) => name,
|
||||
Err(ref err) => {
|
||||
println!(
|
||||
"Something going wrong while getting buffer name: {}",
|
||||
err
|
||||
);
|
||||
"<Error>".to_owned()
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
.filter(|e| e.0)
|
||||
.map(|e| e.1)
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,6 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn set_offset(&mut self, offset: i32, length: i32, num_chars: i32) {
|
||||
self.0.offset = offset;
|
||||
self.0.length = length;
|
||||
self.0.num_chars = num_chars;
|
||||
}
|
||||
|
||||
pub fn analysis(&self) -> analysis::Analysis {
|
||||
analysis::Analysis::from(&self.0.analysis)
|
||||
}
|
||||
|
@ -231,32 +231,6 @@ mod tests {
|
||||
assert_eq!(2, list.list.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_area() {
|
||||
let rect = ModelRect::from_area(10.0, 5.0, 3.0, 3.0, 9.0, 17.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.right);
|
||||
|
||||
|
||||
let rect = ModelRect::from_area(10.0, 5.0, 0.0, 0.0, 10.0, 20.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.right);
|
||||
|
||||
|
||||
let rect = ModelRect::from_area(10.0, 5.0, 0.0, 0.0, 11.0, 21.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(2, rect.bot);
|
||||
assert_eq!(2, rect.right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cursor_area() {
|
||||
let mut model = UiModel::new(10, 20);
|
||||
|
@ -301,4 +301,32 @@ mod tests {
|
||||
assert_eq!(5, width);
|
||||
assert_eq!(10, height);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_from_area() {
|
||||
let rect = ModelRect::from_area(&CellMetrics::new_hw(10.0, 5.0), 3.0, 3.0, 9.0, 17.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.right);
|
||||
|
||||
|
||||
let rect = ModelRect::from_area(&CellMetrics::new_hw(10.0, 5.0), 0.0, 0.0, 10.0, 20.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.right);
|
||||
|
||||
|
||||
let rect = ModelRect::from_area(&CellMetrics::new_hw(10.0, 5.0), 0.0, 0.0, 11.0, 21.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
assert_eq!(2, rect.bot);
|
||||
assert_eq!(2, rect.right);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user