made mouse optional and fixed small issues
This commit is contained in:
parent
cc9c32b981
commit
206c61de9e
|
@ -0,0 +1,41 @@
|
||||||
|
extern crate termion;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use termion::{TermRead, TermWrite, IntoRawMode, Key, Event, MouseEvent};
|
||||||
|
use std::io::{Write, stdout, stdin};
|
||||||
|
|
||||||
|
let stdin = stdin();
|
||||||
|
let mut stdout = stdout().into_raw_mode().unwrap().with_mouse().unwrap();
|
||||||
|
|
||||||
|
stdout.clear().unwrap();
|
||||||
|
stdout.goto(0, 0).unwrap();
|
||||||
|
stdout.write(b"q to exit. Type stuff, use alt, click around...").unwrap();
|
||||||
|
stdout.flush().unwrap();
|
||||||
|
|
||||||
|
let mut x = 0;
|
||||||
|
let mut y = 0;
|
||||||
|
|
||||||
|
for c in stdin.events() {
|
||||||
|
stdout.goto(5, 5).unwrap();
|
||||||
|
stdout.clear_line().unwrap();
|
||||||
|
let evt = c.unwrap();
|
||||||
|
match evt {
|
||||||
|
Event::Key(Key::Char('q')) => break,
|
||||||
|
Event::Mouse(me) => {
|
||||||
|
match me {
|
||||||
|
MouseEvent::Press(_, a, b) |
|
||||||
|
MouseEvent::Release(a, b) => {
|
||||||
|
x = a;
|
||||||
|
y = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
println!("{:?}", evt);
|
||||||
|
stdout.goto(x, y).unwrap();
|
||||||
|
stdout.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout.show_cursor().unwrap();
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
extern crate termion;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
use termion::{TermRead, TermWrite, IntoRawMode, Key, Event};
|
|
||||||
use std::io::{Write, stdout, stdin};
|
|
||||||
|
|
||||||
let stdin = stdin();
|
|
||||||
let mut stdout = stdout().into_raw_mode().unwrap();
|
|
||||||
|
|
||||||
stdout.clear().unwrap();
|
|
||||||
stdout.goto(0, 0).unwrap();
|
|
||||||
stdout.write(b"q to exit. Type stuff, use alt, click around...").unwrap();
|
|
||||||
stdout.flush().unwrap();
|
|
||||||
|
|
||||||
let mut x = 0;
|
|
||||||
let mut y = 0;
|
|
||||||
|
|
||||||
for c in stdin.events() {
|
|
||||||
stdout.goto(5, 5).unwrap();
|
|
||||||
stdout.clear_line().unwrap();
|
|
||||||
match c.unwrap() {
|
|
||||||
Event::KeyEvent(Key::Char('q')) => break,
|
|
||||||
Event::MouseEvent(val, a, b) => {
|
|
||||||
x = a;
|
|
||||||
y = b;
|
|
||||||
println!("{:?}", Event::MouseEvent(val, a, b));
|
|
||||||
},
|
|
||||||
val => println!("{:?}", val),
|
|
||||||
}
|
|
||||||
stdout.goto(x, y).unwrap();
|
|
||||||
stdout.flush().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout.show_cursor().unwrap();
|
|
||||||
}
|
|
127
src/event.rs
127
src/event.rs
|
@ -6,20 +6,20 @@ use std::str;
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// A key press.
|
/// A key press.
|
||||||
KeyEvent(Key),
|
Key(Key),
|
||||||
/// A mouse button press, release or wheel use at specific coordinates.
|
/// A mouse button press, release or wheel use at specific coordinates.
|
||||||
MouseEvent(Mouse, u16, u16),
|
Mouse(MouseEvent),
|
||||||
/// An event that cannot currently be evaluated.
|
/// An event that cannot currently be evaluated.
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mouse related event.
|
/// A mouse related event.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Mouse {
|
pub enum MouseEvent {
|
||||||
/// A mouse button was pressed.
|
/// A mouse button was pressed.
|
||||||
Press(MouseButton),
|
Press(MouseButton, u16, u16),
|
||||||
/// A mouse button was released.
|
/// A mouse button was released.
|
||||||
Release,
|
Release(u16, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mouse button.
|
/// A mouse button.
|
||||||
|
@ -86,6 +86,7 @@ pub enum Key {
|
||||||
__IsNotComplete
|
__IsNotComplete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
|
||||||
pub fn parse_event<I>(item: Result<u8, Error>, iter: &mut I) -> Result<Event, Error>
|
pub fn parse_event<I>(item: Result<u8, Error>, iter: &mut I) -> Result<Event, Error>
|
||||||
where I: Iterator<Item = Result<u8, Error>>
|
where I: Iterator<Item = Result<u8, Error>>
|
||||||
{
|
{
|
||||||
|
@ -95,51 +96,47 @@ where I: Iterator<Item = Result<u8, Error>>
|
||||||
Ok(match iter.next() {
|
Ok(match iter.next() {
|
||||||
Some(Ok(b'O')) => {
|
Some(Ok(b'O')) => {
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(Ok(b'P')) => Event::KeyEvent(Key::F(1)),
|
Some(Ok(val @ b'P' ... b'S')) => Event::Key(Key::F(1 + val - b'P')),
|
||||||
Some(Ok(b'Q')) => Event::KeyEvent(Key::F(2)),
|
|
||||||
Some(Ok(b'R')) => Event::KeyEvent(Key::F(3)),
|
|
||||||
Some(Ok(b'S')) => Event::KeyEvent(Key::F(4)),
|
|
||||||
_ => return error,
|
_ => return error,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Ok(b'[')) => {
|
Some(Ok(b'[')) => {
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(Ok(b'D')) => Event::KeyEvent(Key::Left),
|
Some(Ok(b'D')) => Event::Key(Key::Left),
|
||||||
Some(Ok(b'C')) => Event::KeyEvent(Key::Right),
|
Some(Ok(b'C')) => Event::Key(Key::Right),
|
||||||
Some(Ok(b'A')) => Event::KeyEvent(Key::Up),
|
Some(Ok(b'A')) => Event::Key(Key::Up),
|
||||||
Some(Ok(b'B')) => Event::KeyEvent(Key::Down),
|
Some(Ok(b'B')) => Event::Key(Key::Down),
|
||||||
Some(Ok(b'H')) => Event::KeyEvent(Key::Home),
|
Some(Ok(b'H')) => Event::Key(Key::Home),
|
||||||
Some(Ok(b'F')) => Event::KeyEvent(Key::End),
|
Some(Ok(b'F')) => Event::Key(Key::End),
|
||||||
Some(Ok(b'M')) => {
|
Some(Ok(b'M')) => {
|
||||||
// X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only)
|
// X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
|
||||||
let cb = iter.next().unwrap().unwrap() as i8 - 32;
|
let cb = iter.next().unwrap().unwrap() as i8 - 32;
|
||||||
// (1, 1) are the coords for upper left
|
// (1, 1) are the coords for upper left.
|
||||||
let cx = (iter.next().unwrap().unwrap() as u8 - 1).saturating_sub(32);
|
let cx = (iter.next().unwrap().unwrap() as u8 - 1).saturating_sub(32) as u16;
|
||||||
let cy = (iter.next().unwrap().unwrap() as u8 - 1).saturating_sub(32);
|
let cy = (iter.next().unwrap().unwrap() as u8 - 1).saturating_sub(32) as u16;
|
||||||
Event::MouseEvent(match cb & 0b11 {
|
Event::Mouse(match cb & 0b11 {
|
||||||
0 => {
|
0 => {
|
||||||
if cb & 64 != 0 {
|
if cb & 0x40 != 0 {
|
||||||
Mouse::Press(MouseButton::WheelUp)
|
MouseEvent::Press(MouseButton::WheelUp, cx, cy)
|
||||||
} else {
|
} else {
|
||||||
Mouse::Press(MouseButton::Left)
|
MouseEvent::Press(MouseButton::Left, cx, cy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
if cb & 64 != 0 {
|
if cb & 0x40 != 0 {
|
||||||
Mouse::Press(MouseButton::WheelDown)
|
MouseEvent::Press(MouseButton::WheelDown, cx, cy)
|
||||||
} else {
|
} else {
|
||||||
Mouse::Press(MouseButton::Middle)
|
MouseEvent::Press(MouseButton::Middle, cx, cy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => Mouse::Press(MouseButton::Right),
|
2 => MouseEvent::Press(MouseButton::Right, cx, cy),
|
||||||
3 => Mouse::Release,
|
3 => MouseEvent::Release(cx, cy),
|
||||||
_ => return error,
|
_ => return error,
|
||||||
},
|
})
|
||||||
cx as u16,
|
|
||||||
cy as u16)
|
|
||||||
}
|
}
|
||||||
Some(Ok(b'<')) => {
|
Some(Ok(b'<')) => {
|
||||||
// xterm mouse encoding: ESC [ < Cb ; Cx ; Cy ; (M or m)
|
// xterm mouse encoding:
|
||||||
|
// ESC [ < Cb ; Cx ; Cy ; (M or m)
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let mut c = iter.next().unwrap().unwrap();
|
let mut c = iter.next().unwrap().unwrap();
|
||||||
while match c {
|
while match c {
|
||||||
|
@ -164,17 +161,15 @@ where I: Iterator<Item = Result<u8, Error>>
|
||||||
65 => MouseButton::WheelDown,
|
65 => MouseButton::WheelDown,
|
||||||
_ => return error,
|
_ => return error,
|
||||||
};
|
};
|
||||||
Event::MouseEvent(match c {
|
Event::Mouse(match c {
|
||||||
b'M' => Mouse::Press(button),
|
b'M' => MouseEvent::Press(button, cx, cy),
|
||||||
b'm' => Mouse::Release,
|
b'm' => MouseEvent::Release(cx, cy),
|
||||||
_ => return error,
|
_ => return error,
|
||||||
|
|
||||||
},
|
})
|
||||||
cx,
|
|
||||||
cy)
|
|
||||||
}
|
}
|
||||||
Some(Ok(c @ b'0'...b'9')) => {
|
Some(Ok(c @ b'0'...b'9')) => {
|
||||||
// numbered escape code
|
// Numbered escape code.
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.push(c);
|
buf.push(c);
|
||||||
let mut c = iter.next().unwrap().unwrap();
|
let mut c = iter.next().unwrap().unwrap();
|
||||||
|
@ -187,7 +182,8 @@ where I: Iterator<Item = Result<u8, Error>>
|
||||||
}
|
}
|
||||||
|
|
||||||
match c {
|
match c {
|
||||||
// rxvt mouse encoding: ESC [ Cb ; Cx ; Cy ; M
|
// rxvt mouse encoding:
|
||||||
|
// ESC [ Cb ; Cx ; Cy ; M
|
||||||
b'M' => {
|
b'M' => {
|
||||||
let str_buf = String::from_utf8(buf).unwrap();
|
let str_buf = String::from_utf8(buf).unwrap();
|
||||||
let ref mut nums = str_buf.split(';');
|
let ref mut nums = str_buf.split(';');
|
||||||
|
@ -197,30 +193,30 @@ where I: Iterator<Item = Result<u8, Error>>
|
||||||
let cy = nums.next().unwrap().parse::<u16>().unwrap() - 1;
|
let cy = nums.next().unwrap().parse::<u16>().unwrap() - 1;
|
||||||
|
|
||||||
let event = match cb {
|
let event = match cb {
|
||||||
32 => Mouse::Press(MouseButton::Left),
|
32 => MouseEvent::Press(MouseButton::Left, cx, cy),
|
||||||
33 => Mouse::Press(MouseButton::Middle),
|
33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
|
||||||
34 => Mouse::Press(MouseButton::Right),
|
34 => MouseEvent::Press(MouseButton::Right, cx, cy),
|
||||||
35 => Mouse::Release,
|
35 => MouseEvent::Release(cx, cy),
|
||||||
96 => Mouse::Press(MouseButton::WheelUp),
|
96 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
|
||||||
97 => Mouse::Press(MouseButton::WheelUp),
|
97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
|
||||||
_ => return error,
|
_ => return error,
|
||||||
};
|
};
|
||||||
|
|
||||||
Event::MouseEvent(event, cx, cy)
|
Event::Mouse(event)
|
||||||
},
|
},
|
||||||
// special key code
|
// Special key code.
|
||||||
b'~' => {
|
b'~' => {
|
||||||
let num: u8 = String::from_utf8(buf).unwrap().parse().unwrap();
|
let num: u8 = String::from_utf8(buf).unwrap().parse().unwrap();
|
||||||
match num {
|
match num {
|
||||||
1 | 7 => Event::KeyEvent(Key::Home),
|
1 | 7 => Event::Key(Key::Home),
|
||||||
2 => Event::KeyEvent(Key::Insert),
|
2 => Event::Key(Key::Insert),
|
||||||
3 => Event::KeyEvent(Key::Delete),
|
3 => Event::Key(Key::Delete),
|
||||||
4 | 8 => Event::KeyEvent(Key::End),
|
4 | 8 => Event::Key(Key::End),
|
||||||
5 => Event::KeyEvent(Key::PageUp),
|
5 => Event::Key(Key::PageUp),
|
||||||
6 => Event::KeyEvent(Key::PageDown),
|
6 => Event::Key(Key::PageDown),
|
||||||
v @ 11...15 => Event::KeyEvent(Key::F(v - 10)),
|
v @ 11...15 => Event::Key(Key::F(v - 10)),
|
||||||
v @ 17...21 => Event::KeyEvent(Key::F(v - 11)),
|
v @ 17...21 => Event::Key(Key::F(v - 11)),
|
||||||
v @ 23...24 => Event::KeyEvent(Key::F(v - 12)),
|
v @ 23...24 => Event::Key(Key::F(v - 12)),
|
||||||
_ => return error,
|
_ => return error,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,29 +228,30 @@ where I: Iterator<Item = Result<u8, Error>>
|
||||||
}
|
}
|
||||||
Some(Ok(c)) => {
|
Some(Ok(c)) => {
|
||||||
let ch = parse_utf8_char(c, iter);
|
let ch = parse_utf8_char(c, iter);
|
||||||
Event::KeyEvent(Key::Alt(try!(ch)))
|
Event::Key(Key::Alt(try!(ch)))
|
||||||
}
|
}
|
||||||
Some(Err(_)) | None => return error,
|
Some(Err(_)) | None => return error,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Ok(b'\n') | Ok(b'\r') => Ok(Event::KeyEvent(Key::Char('\n'))),
|
Ok(b'\n') | Ok(b'\r') => Ok(Event::Key(Key::Char('\n'))),
|
||||||
Ok(b'\t') => Ok(Event::KeyEvent(Key::Char('\t'))),
|
Ok(b'\t') => Ok(Event::Key(Key::Char('\t'))),
|
||||||
Ok(b'\x7F') => Ok(Event::KeyEvent(Key::Backspace)),
|
Ok(b'\x7F') => Ok(Event::Key(Key::Backspace)),
|
||||||
Ok(c @ b'\x01'...b'\x1A') => Ok(Event::KeyEvent(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
|
Ok(c @ b'\x01'...b'\x1A') => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
|
||||||
Ok(c @ b'\x1C'...b'\x1F') => {
|
Ok(c @ b'\x1C'...b'\x1F') => {
|
||||||
Ok(Event::KeyEvent(Key::Ctrl((c as u8 - 0x1C + b'4') as char)))
|
Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char)))
|
||||||
}
|
}
|
||||||
Ok(b'\0') => Ok(Event::KeyEvent(Key::Null)),
|
Ok(b'\0') => Ok(Event::Key(Key::Null)),
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
Ok({
|
Ok({
|
||||||
let ch = parse_utf8_char(c, iter);
|
let ch = parse_utf8_char(c, iter);
|
||||||
Event::KeyEvent(Key::Char(try!(ch)))
|
Event::Key(Key::Char(try!(ch)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
|
||||||
fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
|
fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
|
||||||
where I: Iterator<Item = Result<u8, Error>>
|
where I: Iterator<Item = Result<u8, Error>>
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl<I: Iterator<Item = Result<u8, io::Error>>> Iterator for Keys<I> {
|
||||||
fn next(&mut self) -> Option<Result<Key, io::Error>> {
|
fn next(&mut self) -> Option<Result<Key, io::Error>> {
|
||||||
loop {
|
loop {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
Some(Ok(Event::KeyEvent(k))) => return Some(Ok(k)),
|
Some(Ok(Event::Key(k))) => return Some(Ok(k)),
|
||||||
Some(Ok(_)) => continue,
|
Some(Ok(_)) => continue,
|
||||||
e @ Some(Err(_)) => e,
|
e @ Some(Err(_)) => e,
|
||||||
None => return None,
|
None => return None,
|
||||||
|
|
|
@ -27,10 +27,10 @@ mod input;
|
||||||
pub use input::{TermRead, Events, Keys};
|
pub use input::{TermRead, Events, Keys};
|
||||||
|
|
||||||
mod event;
|
mod event;
|
||||||
pub use event::{Key, Mouse, MouseButton, Event};
|
pub use event::{Key, MouseEvent, MouseButton, Event};
|
||||||
|
|
||||||
mod raw;
|
mod raw;
|
||||||
pub use raw::{IntoRawMode, RawTerminal};
|
pub use raw::{IntoRawMode, RawTerminal, MouseTerminal};
|
||||||
|
|
||||||
mod size;
|
mod size;
|
||||||
pub use size::terminal_size;
|
pub use size::terminal_size;
|
||||||
|
|
72
src/raw.rs
72
src/raw.rs
|
@ -1,9 +1,6 @@
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
const ENTER_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h";
|
|
||||||
const EXIT_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l";
|
|
||||||
|
|
||||||
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
|
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
|
||||||
/// dropped.
|
/// dropped.
|
||||||
#[cfg(target_os = "redox")]
|
#[cfg(target_os = "redox")]
|
||||||
|
@ -15,7 +12,6 @@ pub struct RawTerminal<W: Write> {
|
||||||
impl<W: Write> Drop for RawTerminal<W> {
|
impl<W: Write> Drop for RawTerminal<W> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
use control::TermWrite;
|
use control::TermWrite;
|
||||||
try!(self.write(EXIT_MOUSE_SEQUENCE));
|
|
||||||
self.csi(b"R").unwrap();
|
self.csi(b"R").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +26,21 @@ pub struct RawTerminal<W: Write> {
|
||||||
output: W,
|
output: W,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
impl<W> RawTerminal<W>
|
||||||
|
where W: Write
|
||||||
|
{
|
||||||
|
/// Enable mouse support.
|
||||||
|
pub fn with_mouse(mut self) -> io::Result<MouseTerminal<W>> {
|
||||||
|
try!(self.write(ENTER_MOUSE_SEQUENCE));
|
||||||
|
Ok(MouseTerminal { term: self })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "redox"))]
|
#[cfg(not(target_os = "redox"))]
|
||||||
impl<W: Write> Drop for RawTerminal<W> {
|
impl<W: Write> Drop for RawTerminal<W> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
use termios::set_terminal_attr;
|
use termios::set_terminal_attr;
|
||||||
self.write(EXIT_MOUSE_SEQUENCE).unwrap();
|
|
||||||
set_terminal_attr(&mut self.prev_ios as *mut _);
|
set_terminal_attr(&mut self.prev_ios as *mut _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,11 +97,10 @@ impl<W: Write> IntoRawMode for W {
|
||||||
if set_terminal_attr(&mut ios as *mut _) != 0 {
|
if set_terminal_attr(&mut ios as *mut _) != 0 {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
|
Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
|
||||||
} else {
|
} else {
|
||||||
let mut res = RawTerminal {
|
let res = RawTerminal {
|
||||||
prev_ios: prev_ios,
|
prev_ios: prev_ios,
|
||||||
output: self,
|
output: self,
|
||||||
};
|
};
|
||||||
try!(res.write(ENTER_MOUSE_SEQUENCE));
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,14 +111,63 @@ impl<W: Write> IntoRawMode for W {
|
||||||
|
|
||||||
self.csi(b"r").map(|_| {
|
self.csi(b"r").map(|_| {
|
||||||
let mut res = RawTerminal {
|
let mut res = RawTerminal {
|
||||||
output: self,
|
output: self,
|
||||||
};
|
};
|
||||||
try!(res.write(ENTER_MOUSE_SEQUENCE));
|
|
||||||
res
|
res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A sequence of escape codes to enable terminal mouse support.
|
||||||
|
const ENTER_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h";
|
||||||
|
|
||||||
|
/// A sequence of escape codes to disable terminal mouse support.
|
||||||
|
const EXIT_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l";
|
||||||
|
|
||||||
|
/// A `RawTerminal` with added mouse support.
|
||||||
|
///
|
||||||
|
/// To get such a terminal handle use `RawTerminal`'s
|
||||||
|
/// [`with_mouse()`](../termion/struct.RawTerminal.html#method.with_mouse) method.
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
pub struct MouseTerminal<W: Write> {
|
||||||
|
term: RawTerminal<W>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
impl<W: Write> Drop for MouseTerminal<W> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.term.write(EXIT_MOUSE_SEQUENCE).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
impl<W: Write> Deref for MouseTerminal<W> {
|
||||||
|
type Target = W;
|
||||||
|
|
||||||
|
fn deref(&self) -> &W {
|
||||||
|
self.term.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
impl<W: Write> DerefMut for MouseTerminal<W> {
|
||||||
|
fn deref_mut(&mut self) -> &mut W {
|
||||||
|
self.term.deref_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
impl<W: Write> Write for MouseTerminal<W> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.term.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.term.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue