mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Add mouse support to pancurses
This commit is contained in:
parent
ee7170c66b
commit
0b5b6ceace
39
Cargo.toml
39
Cargo.toml
@ -1,10 +1,21 @@
|
|||||||
[package]
|
[package]
|
||||||
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
||||||
categories = ["command-line-interface", "gui"]
|
categories = [
|
||||||
|
"command-line-interface",
|
||||||
|
"gui",
|
||||||
|
]
|
||||||
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
||||||
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
||||||
exclude = ["doc/**", "assets/**", "examples/**"]
|
exclude = [
|
||||||
keywords = ["ncurses", "TUI", "UI"]
|
"doc/**",
|
||||||
|
"assets/**",
|
||||||
|
"examples/**",
|
||||||
|
]
|
||||||
|
keywords = [
|
||||||
|
"ncurses",
|
||||||
|
"TUI",
|
||||||
|
"UI",
|
||||||
|
]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
readme = "Readme.md"
|
readme = "Readme.md"
|
||||||
@ -14,7 +25,6 @@ version = "0.7.5-alpha.0"
|
|||||||
[badges.travis-ci]
|
[badges.travis-ci]
|
||||||
repository = "gyscos/Cursive"
|
repository = "gyscos/Cursive"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
num = "0.1"
|
num = "0.1"
|
||||||
@ -24,6 +34,10 @@ toml = "0.4"
|
|||||||
unicode-segmentation = "1.0"
|
unicode-segmentation = "1.0"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
|
|
||||||
|
[dependencies.bear-lib-terminal]
|
||||||
|
optional = true
|
||||||
|
version = "1.3.1"
|
||||||
|
|
||||||
[dependencies.chan]
|
[dependencies.chan]
|
||||||
optional = true
|
optional = true
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
@ -32,10 +46,6 @@ version = "0.1.18"
|
|||||||
optional = true
|
optional = true
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
|
|
||||||
[dependencies.bear-lib-terminal]
|
|
||||||
optional = true
|
|
||||||
version = "1.3.1"
|
|
||||||
|
|
||||||
[dependencies.ncurses]
|
[dependencies.ncurses]
|
||||||
features = ["wide"]
|
features = ["wide"]
|
||||||
optional = true
|
optional = true
|
||||||
@ -54,12 +64,15 @@ version = "1.5.0"
|
|||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ncurses-backend"]
|
|
||||||
|
|
||||||
ncurses-backend = ["ncurses"]
|
|
||||||
termion-backend = ["termion", "chan", "chan-signal"]
|
|
||||||
pancurses-backend = ["pancurses"]
|
|
||||||
blt-backend = ["bear-lib-terminal"]
|
blt-backend = ["bear-lib-terminal"]
|
||||||
|
default = ["ncurses-backend"]
|
||||||
|
ncurses-backend = ["ncurses"]
|
||||||
|
pancurses-backend = ["pancurses"]
|
||||||
|
termion-backend = [
|
||||||
|
"termion",
|
||||||
|
"chan",
|
||||||
|
"chan-signal",
|
||||||
|
]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
|
@ -4,6 +4,7 @@ use cursive::{Cursive, Printer};
|
|||||||
use cursive::event::{Event, EventResult};
|
use cursive::event::{Event, EventResult};
|
||||||
use cursive::traits::*;
|
use cursive::traits::*;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut siv = Cursive::new();
|
let mut siv = Cursive::new();
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ mod pan;
|
|||||||
#[cfg(feature = "pancurses")]
|
#[cfg(feature = "pancurses")]
|
||||||
pub use self::pan::*;
|
pub use self::pan::*;
|
||||||
|
|
||||||
|
fn split_u32(code: i32) -> Vec<u8> {
|
||||||
|
(0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn find_closest(color: &Color) -> i16 {
|
fn find_closest(color: &Color) -> i16 {
|
||||||
match *color {
|
match *color {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
extern crate ncurses;
|
extern crate ncurses;
|
||||||
|
|
||||||
use self::super::find_closest;
|
use self::ncurses::mmask_t;
|
||||||
|
use self::super::{find_closest, split_u32};
|
||||||
use backend;
|
use backend;
|
||||||
use event::{Event, Key, MouseButton, MouseEvent};
|
use event::{Event, Key, MouseButton, MouseEvent};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
@ -78,17 +79,17 @@ impl Concrete {
|
|||||||
// eprintln!("{:032b}", mevent.bstate);
|
// eprintln!("{:032b}", mevent.bstate);
|
||||||
// Currently unused
|
// Currently unused
|
||||||
let _shift = (mevent.bstate
|
let _shift = (mevent.bstate
|
||||||
& ncurses::BUTTON_SHIFT as ncurses::mmask_t)
|
& ncurses::BUTTON_SHIFT as mmask_t)
|
||||||
!= 0;
|
!= 0;
|
||||||
let _alt =
|
let _alt =
|
||||||
(mevent.bstate & ncurses::BUTTON_ALT as ncurses::mmask_t) != 0;
|
(mevent.bstate & ncurses::BUTTON_ALT as mmask_t) != 0;
|
||||||
let _ctrl = (mevent.bstate
|
let _ctrl = (mevent.bstate
|
||||||
& ncurses::BUTTON_CTRL as ncurses::mmask_t)
|
& ncurses::BUTTON_CTRL as mmask_t)
|
||||||
!= 0;
|
!= 0;
|
||||||
|
|
||||||
mevent.bstate &= !(ncurses::BUTTON_SHIFT | ncurses::BUTTON_ALT
|
mevent.bstate &= !(ncurses::BUTTON_SHIFT | ncurses::BUTTON_ALT
|
||||||
| ncurses::BUTTON_CTRL)
|
| ncurses::BUTTON_CTRL)
|
||||||
as ncurses::mmask_t;
|
as mmask_t;
|
||||||
|
|
||||||
let make_event = |event| {
|
let make_event = |event| {
|
||||||
Event::Mouse {
|
Event::Mouse {
|
||||||
@ -99,7 +100,7 @@ impl Concrete {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if mevent.bstate
|
if mevent.bstate
|
||||||
== ncurses::REPORT_MOUSE_POSITION as ncurses::mmask_t
|
== ncurses::REPORT_MOUSE_POSITION as mmask_t
|
||||||
{
|
{
|
||||||
// The event is either a mouse drag event,
|
// The event is either a mouse drag event,
|
||||||
// or a weird double-release event. :S
|
// or a weird double-release event. :S
|
||||||
@ -117,7 +118,7 @@ impl Concrete {
|
|||||||
bare_event ^= single_event;
|
bare_event ^= single_event;
|
||||||
|
|
||||||
// Process single_event
|
// Process single_event
|
||||||
get_event(single_event as i32, |e| if event.is_none() {
|
on_mouse_event(single_event as i32, |e| if event.is_none() {
|
||||||
event = Some(e);
|
event = Some(e);
|
||||||
} else {
|
} else {
|
||||||
self.event_queue.push(make_event(e));
|
self.event_queue.push(make_event(e));
|
||||||
@ -256,11 +257,7 @@ impl Concrete {
|
|||||||
c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
|
c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
|
||||||
other => {
|
other => {
|
||||||
// Split the i32 into 4 bytes
|
// Split the i32 into 4 bytes
|
||||||
Event::Unknown(
|
Event::Unknown(split_u32(other))
|
||||||
(0..4)
|
|
||||||
.map(|i| ((other >> (8 * i)) & 0xFF) as u8)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,7 +283,7 @@ impl backend::Backend for Concrete {
|
|||||||
// Listen to all mouse events.
|
// Listen to all mouse events.
|
||||||
ncurses::mousemask(
|
ncurses::mousemask(
|
||||||
(ncurses::ALL_MOUSE_EVENTS | ncurses::REPORT_MOUSE_POSITION)
|
(ncurses::ALL_MOUSE_EVENTS | ncurses::REPORT_MOUSE_POSITION)
|
||||||
as ncurses::mmask_t,
|
as mmask_t,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
ncurses::noecho();
|
ncurses::noecho();
|
||||||
@ -395,7 +392,7 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Key enum corresponding to the given ncurses event.
|
/// Returns the Key enum corresponding to the given ncurses event.
|
||||||
fn get_button(bare_event: i32) -> MouseButton {
|
fn get_mouse_button(bare_event: i32) -> MouseButton {
|
||||||
match bare_event {
|
match bare_event {
|
||||||
ncurses::BUTTON1_RELEASED |
|
ncurses::BUTTON1_RELEASED |
|
||||||
ncurses::BUTTON1_PRESSED |
|
ncurses::BUTTON1_PRESSED |
|
||||||
@ -433,11 +430,11 @@ fn get_button(bare_event: i32) -> MouseButton {
|
|||||||
/// the returned Vec will include those queued events.
|
/// the returned Vec will include those queued events.
|
||||||
///
|
///
|
||||||
/// The main event is returned separately to avoid allocation in most cases.
|
/// The main event is returned separately to avoid allocation in most cases.
|
||||||
fn get_event<F>(bare_event: i32, mut f: F)
|
fn on_mouse_event<F>(bare_event: i32, mut f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(MouseEvent),
|
F: FnMut(MouseEvent),
|
||||||
{
|
{
|
||||||
let button = get_button(bare_event);
|
let button = get_mouse_button(bare_event);
|
||||||
match bare_event {
|
match bare_event {
|
||||||
ncurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp),
|
ncurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp),
|
||||||
ncurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown),
|
ncurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown),
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
extern crate pancurses;
|
extern crate pancurses;
|
||||||
|
|
||||||
use self::super::find_closest;
|
use self::pancurses::mmask_t;
|
||||||
|
use self::super::{find_closest, split_u32};
|
||||||
use backend;
|
use backend;
|
||||||
use event::{Event, Key};
|
use event::{Event, Key, MouseButton, MouseEvent};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use theme::{Color, ColorPair, Effect};
|
use theme::{Color, ColorPair, Effect};
|
||||||
use utf8;
|
use utf8;
|
||||||
|
use vec::Vec2;
|
||||||
|
|
||||||
pub struct Concrete {
|
pub struct Concrete {
|
||||||
current_style: Cell<ColorPair>,
|
current_style: Cell<ColorPair>,
|
||||||
pairs: RefCell<HashMap<ColorPair, i32>>,
|
pairs: RefCell<HashMap<ColorPair, i32>>,
|
||||||
window: pancurses::Window,
|
window: pancurses::Window,
|
||||||
|
|
||||||
|
last_mouse_button: Option<MouseButton>,
|
||||||
|
event_queue: Vec<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Concrete {
|
impl Concrete {
|
||||||
@ -61,23 +66,102 @@ impl Concrete {
|
|||||||
let style = pancurses::COLOR_PAIR(i as pancurses::chtype);
|
let style = pancurses::COLOR_PAIR(i as pancurses::chtype);
|
||||||
self.window.attron(style);
|
self.window.attron(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_mouse_event(&mut self) -> Event {
|
||||||
|
let mut mevent = match pancurses::getmouse() {
|
||||||
|
Err(code) => return Event::Unknown(split_u32(code)),
|
||||||
|
Ok(event) => event,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _shift =
|
||||||
|
(mevent.bstate & pancurses::BUTTON_SHIFT as mmask_t) != 0;
|
||||||
|
let _alt =
|
||||||
|
(mevent.bstate & pancurses::BUTTON_ALT as mmask_t) != 0;
|
||||||
|
let _ctrl =
|
||||||
|
(mevent.bstate & pancurses::BUTTON_CTRL as mmask_t) != 0;
|
||||||
|
|
||||||
|
mevent.bstate &= !(pancurses::BUTTON_SHIFT | pancurses::BUTTON_ALT
|
||||||
|
| pancurses::BUTTON_CTRL)
|
||||||
|
as mmask_t;
|
||||||
|
|
||||||
|
let make_event = |event| {
|
||||||
|
Event::Mouse {
|
||||||
|
offset: Vec2::zero(),
|
||||||
|
position: Vec2::new(mevent.x as usize, mevent.y as usize),
|
||||||
|
event: event,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if mevent.bstate == pancurses::REPORT_MOUSE_POSITION as mmask_t
|
||||||
|
{
|
||||||
|
// The event is either a mouse drag event,
|
||||||
|
// or a weird double-release event. :S
|
||||||
|
self.last_mouse_button
|
||||||
|
.map(MouseEvent::Hold)
|
||||||
|
.map(&make_event)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
debug!("We got a mouse drag, but no last mouse pressed?");
|
||||||
|
Event::Unknown(vec![])
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Identify the button
|
||||||
|
let mut bare_event = mevent.bstate & ((1 << 25) - 1);
|
||||||
|
|
||||||
|
let mut event = None;
|
||||||
|
while bare_event != 0 {
|
||||||
|
let single_event = 1 << bare_event.trailing_zeros();
|
||||||
|
bare_event ^= single_event;
|
||||||
|
|
||||||
|
// Process single_event
|
||||||
|
on_mouse_event(single_event, |e| {
|
||||||
|
if event.is_none() {
|
||||||
|
event = Some(e);
|
||||||
|
} else {
|
||||||
|
self.event_queue.push(make_event(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(event) = event {
|
||||||
|
if let Some(btn) = event.button() {
|
||||||
|
self.last_mouse_button = Some(btn);
|
||||||
|
}
|
||||||
|
make_event(event)
|
||||||
|
} else {
|
||||||
|
debug!("No event parsed?...");
|
||||||
|
Event::Unknown(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl backend::Backend for Concrete {
|
impl backend::Backend for Concrete {
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
let window = pancurses::initscr();
|
|
||||||
::std::env::set_var("ESCDELAY", "25");
|
::std::env::set_var("ESCDELAY", "25");
|
||||||
|
|
||||||
|
let window = pancurses::initscr();
|
||||||
window.keypad(true);
|
window.keypad(true);
|
||||||
pancurses::noecho();
|
pancurses::noecho();
|
||||||
pancurses::cbreak();
|
pancurses::cbreak();
|
||||||
pancurses::start_color();
|
pancurses::start_color();
|
||||||
pancurses::use_default_colors();
|
pancurses::use_default_colors();
|
||||||
pancurses::curs_set(0);
|
pancurses::curs_set(0);
|
||||||
|
pancurses::mouseinterval(0);
|
||||||
|
pancurses::mousemask(
|
||||||
|
pancurses::ALL_MOUSE_EVENTS | pancurses::REPORT_MOUSE_POSITION,
|
||||||
|
::std::ptr::null_mut(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// This asks the terminal to provide us with mouse drag events
|
||||||
|
// (Mouse move when a button is pressed).
|
||||||
|
// Replacing 1002 with 1003 would give us ANY mouse move.
|
||||||
|
println!("\x1B[?1002h");
|
||||||
|
|
||||||
Concrete {
|
Concrete {
|
||||||
current_style: Cell::new(ColorPair::from_256colors(0, 0)),
|
current_style: Cell::new(ColorPair::from_256colors(0, 0)),
|
||||||
pairs: RefCell::new(HashMap::new()),
|
pairs: RefCell::new(HashMap::new()),
|
||||||
window: window,
|
window: window,
|
||||||
|
last_mouse_button: None,
|
||||||
|
event_queue: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,8 +220,7 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll_event(&mut self) -> Event {
|
fn poll_event(&mut self) -> Event {
|
||||||
// TODO: there seems to not be any indication
|
self.event_queue.pop().unwrap_or_else(|| {
|
||||||
// of Ctrl/Alt/Shift in these :v
|
|
||||||
if let Some(ev) = self.window.getch() {
|
if let Some(ev) = self.window.getch() {
|
||||||
match ev {
|
match ev {
|
||||||
pancurses::Input::Character('\n') => Event::Key(Key::Enter),
|
pancurses::Input::Character('\n') => Event::Key(Key::Enter),
|
||||||
@ -163,6 +246,9 @@ impl backend::Backend for Concrete {
|
|||||||
}).unwrap(),
|
}).unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
pancurses::Input::Character(c) if (c as u32) <= 26 => {
|
||||||
|
Event::CtrlChar((b'a' - 1 + c as u8) as char)
|
||||||
|
}
|
||||||
pancurses::Input::Character(c) => {
|
pancurses::Input::Character(c) => {
|
||||||
let mut bytes = [0u8; 4];
|
let mut bytes = [0u8; 4];
|
||||||
Event::Unknown(
|
Event::Unknown(
|
||||||
@ -171,11 +257,53 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
// TODO: Some key combos are not recognized by pancurses,
|
// TODO: Some key combos are not recognized by pancurses,
|
||||||
// but are sent as Unknown. We could still parse them here.
|
// but are sent as Unknown. We could still parse them here.
|
||||||
pancurses::Input::Unknown(other) => Event::Unknown(
|
pancurses::Input::Unknown(code) => match code {
|
||||||
(0..4)
|
220 => Event::Ctrl(Key::Del),
|
||||||
.map(|i| ((other >> (8 * i)) & 0xFF) as u8)
|
|
||||||
.collect(),
|
224 => Event::Alt(Key::Down),
|
||||||
),
|
225 => Event::AltShift(Key::Down),
|
||||||
|
226 => Event::Ctrl(Key::Down),
|
||||||
|
227 => Event::CtrlShift(Key::Down),
|
||||||
|
|
||||||
|
229 => Event::Alt(Key::End),
|
||||||
|
230 => Event::AltShift(Key::End),
|
||||||
|
231 => Event::Ctrl(Key::End),
|
||||||
|
232 => Event::CtrlShift(Key::End),
|
||||||
|
|
||||||
|
235 => Event::Alt(Key::Home),
|
||||||
|
236 => Event::AltShift(Key::Home),
|
||||||
|
237 => Event::Ctrl(Key::Home),
|
||||||
|
238 => Event::CtrlShift(Key::Home),
|
||||||
|
|
||||||
|
246 => Event::Alt(Key::Left),
|
||||||
|
247 => Event::AltShift(Key::Left),
|
||||||
|
248 => Event::Ctrl(Key::Left),
|
||||||
|
249 => Event::CtrlShift(Key::Left),
|
||||||
|
|
||||||
|
251 => Event::Alt(Key::PageDown),
|
||||||
|
252 => Event::AltShift(Key::PageDown),
|
||||||
|
253 => Event::Ctrl(Key::PageDown),
|
||||||
|
254 => Event::CtrlShift(Key::PageDown),
|
||||||
|
|
||||||
|
256 => Event::Alt(Key::PageUp),
|
||||||
|
257 => Event::AltShift(Key::PageUp),
|
||||||
|
258 => Event::Ctrl(Key::PageUp),
|
||||||
|
259 => Event::CtrlShift(Key::PageUp),
|
||||||
|
|
||||||
|
261 => Event::Alt(Key::Right),
|
||||||
|
262 => Event::AltShift(Key::Right),
|
||||||
|
263 => Event::Ctrl(Key::Right),
|
||||||
|
264 => Event::CtrlShift(Key::Right),
|
||||||
|
|
||||||
|
267 => Event::Alt(Key::Up),
|
||||||
|
268 => Event::AltShift(Key::Up),
|
||||||
|
269 => Event::Ctrl(Key::Up),
|
||||||
|
270 => Event::CtrlShift(Key::Up),
|
||||||
|
other => {
|
||||||
|
eprintln!("Unknown: {}", other);
|
||||||
|
Event::Unknown(split_u32(other))
|
||||||
|
}
|
||||||
|
},
|
||||||
// TODO: I honestly have no fucking idea what KeyCodeYes is
|
// TODO: I honestly have no fucking idea what KeyCodeYes is
|
||||||
pancurses::Input::KeyCodeYes => Event::Refresh,
|
pancurses::Input::KeyCodeYes => Event::Refresh,
|
||||||
pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
|
pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
|
||||||
@ -282,7 +410,7 @@ impl backend::Backend for Concrete {
|
|||||||
pancurses::Input::KeyResize => Event::WindowResize,
|
pancurses::Input::KeyResize => Event::WindowResize,
|
||||||
pancurses::Input::KeyEvent => Event::Refresh,
|
pancurses::Input::KeyEvent => Event::Refresh,
|
||||||
// TODO: mouse support
|
// TODO: mouse support
|
||||||
pancurses::Input::KeyMouse => Event::Refresh,
|
pancurses::Input::KeyMouse => self.parse_mouse_event(),
|
||||||
pancurses::Input::KeyA1 => Event::Refresh,
|
pancurses::Input::KeyA1 => Event::Refresh,
|
||||||
pancurses::Input::KeyA3 => Event::Refresh,
|
pancurses::Input::KeyA3 => Event::Refresh,
|
||||||
pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
|
pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
|
||||||
@ -292,6 +420,7 @@ impl backend::Backend for Concrete {
|
|||||||
} else {
|
} else {
|
||||||
Event::Refresh
|
Event::Refresh
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_refresh_rate(&mut self, fps: u32) {
|
fn set_refresh_rate(&mut self, fps: u32) {
|
||||||
@ -302,3 +431,88 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse the given code into one or more event.
|
||||||
|
///
|
||||||
|
/// If the given event code should expend into multiple events
|
||||||
|
/// (for instance click expends into PRESS + RELEASE),
|
||||||
|
/// the returned Vec will include those queued events.
|
||||||
|
///
|
||||||
|
/// The main event is returned separately to avoid allocation in most cases.
|
||||||
|
fn on_mouse_event<F>(bare_event: u32, mut f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(MouseEvent),
|
||||||
|
{
|
||||||
|
let button = get_mouse_button(bare_event);
|
||||||
|
match bare_event {
|
||||||
|
pancurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp),
|
||||||
|
pancurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown),
|
||||||
|
pancurses::BUTTON1_RELEASED |
|
||||||
|
pancurses::BUTTON2_RELEASED |
|
||||||
|
pancurses::BUTTON3_RELEASED |
|
||||||
|
pancurses::BUTTON4_RELEASED |
|
||||||
|
pancurses::BUTTON5_RELEASED => f(MouseEvent::Release(button)),
|
||||||
|
pancurses::BUTTON1_PRESSED |
|
||||||
|
pancurses::BUTTON2_PRESSED |
|
||||||
|
pancurses::BUTTON3_PRESSED => f(MouseEvent::Press(button)),
|
||||||
|
pancurses::BUTTON1_CLICKED |
|
||||||
|
pancurses::BUTTON2_CLICKED |
|
||||||
|
pancurses::BUTTON3_CLICKED |
|
||||||
|
pancurses::BUTTON4_CLICKED |
|
||||||
|
pancurses::BUTTON5_CLICKED => {
|
||||||
|
f(MouseEvent::Press(button));
|
||||||
|
f(MouseEvent::Release(button));
|
||||||
|
}
|
||||||
|
// Well, we disabled click detection
|
||||||
|
pancurses::BUTTON1_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON2_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON3_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON4_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON5_DOUBLE_CLICKED => for _ in 0..2 {
|
||||||
|
f(MouseEvent::Press(button));
|
||||||
|
f(MouseEvent::Release(button));
|
||||||
|
},
|
||||||
|
pancurses::BUTTON1_TRIPLE_CLICKED |
|
||||||
|
pancurses::BUTTON2_TRIPLE_CLICKED |
|
||||||
|
pancurses::BUTTON3_TRIPLE_CLICKED |
|
||||||
|
pancurses::BUTTON4_TRIPLE_CLICKED |
|
||||||
|
pancurses::BUTTON5_TRIPLE_CLICKED => for _ in 0..3 {
|
||||||
|
f(MouseEvent::Press(button));
|
||||||
|
f(MouseEvent::Release(button));
|
||||||
|
},
|
||||||
|
_ => debug!("Unknown event: {:032b}", bare_event),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Key enum corresponding to the given pancurses event.
|
||||||
|
fn get_mouse_button(bare_event: u32) -> MouseButton {
|
||||||
|
match bare_event {
|
||||||
|
pancurses::BUTTON1_RELEASED |
|
||||||
|
pancurses::BUTTON1_PRESSED |
|
||||||
|
pancurses::BUTTON1_CLICKED |
|
||||||
|
pancurses::BUTTON1_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON1_TRIPLE_CLICKED => MouseButton::Left,
|
||||||
|
pancurses::BUTTON2_RELEASED |
|
||||||
|
pancurses::BUTTON2_PRESSED |
|
||||||
|
pancurses::BUTTON2_CLICKED |
|
||||||
|
pancurses::BUTTON2_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON2_TRIPLE_CLICKED => MouseButton::Middle,
|
||||||
|
pancurses::BUTTON3_RELEASED |
|
||||||
|
pancurses::BUTTON3_PRESSED |
|
||||||
|
pancurses::BUTTON3_CLICKED |
|
||||||
|
pancurses::BUTTON3_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON3_TRIPLE_CLICKED => MouseButton::Right,
|
||||||
|
pancurses::BUTTON4_RELEASED |
|
||||||
|
pancurses::BUTTON4_PRESSED |
|
||||||
|
pancurses::BUTTON4_CLICKED |
|
||||||
|
pancurses::BUTTON4_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON4_TRIPLE_CLICKED => MouseButton::Button4,
|
||||||
|
pancurses::BUTTON5_RELEASED |
|
||||||
|
pancurses::BUTTON5_PRESSED |
|
||||||
|
pancurses::BUTTON5_CLICKED |
|
||||||
|
pancurses::BUTTON5_DOUBLE_CLICKED |
|
||||||
|
pancurses::BUTTON5_TRIPLE_CLICKED => MouseButton::Button5,
|
||||||
|
_ => MouseButton::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user