From 858067ef6b7eff1f6a26199d662367a04df924ab Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 13 Dec 2016 22:10:00 -0800 Subject: [PATCH] Detect terminal resize in termion backend Using the chan_signal crate --- Cargo.toml | 12 ++++++++---- src/backend/termion.rs | 36 ++++++++++++++++++++++++++---------- src/lib.rs | 3 +++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9d4fe75..a3d35d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,16 +11,24 @@ readme = "Readme.md" repository = "https://github.com/gyscos/Cursive" version = "0.3.5" +[build-dependencies] + [build-dependencies.skeptic] optional = true version = "0.6" [dependencies] +chan = "0.1.18" +chan-signal = "0.1" odds = "0.2" toml = "0.2" unicode-segmentation = "0.1" unicode-width = "0.1" +[dependencies.bear-lib-terminal] +optional = true +version = "1.3.1" + [dependencies.ncurses] features = ["wide"] optional = true @@ -35,10 +43,6 @@ version = "0.7" optional = true version = "1.1.1" -[dependencies.bear-lib-terminal] -optional = true -version = "1.3.1" - [dev-dependencies] rand = "0.3" skeptic = "0.6" diff --git a/src/backend/termion.rs b/src/backend/termion.rs index 9f14b46..56277c0 100644 --- a/src/backend/termion.rs +++ b/src/backend/termion.rs @@ -1,5 +1,7 @@ extern crate termion; +extern crate chan_signal; + use ::backend; use ::event::{Event, Key}; use self::termion::color as tcolor; @@ -11,9 +13,9 @@ use std::cell::Cell; use std::collections::BTreeMap; use std::fmt; use std::io::Write; -use std::sync::mpsc; use std::thread; use std::time; +use chan; use ::theme; @@ -22,8 +24,9 @@ pub struct Concrete { current_style: Cell, colors: BTreeMap, Box)>, - input: mpsc::Receiver, - timeout: Option, + input: chan::Receiver, + resize: chan::Receiver, + timeout: Option, } trait Effectable { @@ -75,17 +78,18 @@ impl Concrete { impl backend::Backend for Concrete { fn init() -> Self { print!("{}", termion::cursor::Hide); + + let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]); + let terminal = ::std::io::stdout().into_raw_mode().unwrap(); - let (sender, receiver) = mpsc::channel(); + let (sender, receiver) = chan::async(); // TODO: use signal_chan crate thread::spawn(move || { for key in ::std::io::stdin().keys() { if let Ok(key) = key { - if sender.send(map_key(key)).is_err() { - break; - } + sender.send(map_key(key)) } } }); @@ -95,6 +99,7 @@ impl backend::Backend for Concrete { current_style: Cell::new(theme::ColorStyle::Background), colors: BTreeMap::new(), input: receiver, + resize: resize, timeout: None, }; @@ -167,16 +172,27 @@ impl backend::Backend for Concrete { // TODO: handle async refresh, when no input is entered. // Could be done with a timeout on the event polling, // if it was supportedd. - self.timeout = Some(time::Duration::from_millis(1000 / fps as u64)); + self.timeout = Some(1000 / fps as u32); } fn poll_event(&self) -> Event { // TODO: select! on the input and SIGWINCH signal channel. // TODO: also handle timeout... recv_timeout? + let input = &self.input; + let resize = &self.resize; + if let Some(timeout) = self.timeout { - self.input.recv_timeout(timeout).unwrap_or(Event::Refresh) + let timeout = chan::after_ms(timeout); + chan_select!{ + timeout.recv() => return Event::Refresh, + resize.recv() => return Event::WindowResize, + input.recv() -> input => return input.unwrap(), + } } else { - self.input.recv().unwrap() + chan_select!{ + resize.recv() => return Event::WindowResize, + input.recv() -> input => return input.unwrap(), + } } } } diff --git a/src/lib.rs b/src/lib.rs index 0fb0e32..effb2c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,9 @@ extern crate unicode_segmentation; extern crate unicode_width; extern crate odds; +#[macro_use] +extern crate chan; + macro_rules! println_stderr( ($($arg:tt)*) => { { use ::std::io::Write;