mirror of
https://github.com/Xyverle/neutuino.git
synced 2026-06-26 22:23:14 -04:00
something probably
This commit is contained in:
21
src/input.rs
21
src/input.rs
@@ -19,7 +19,6 @@ pub use windows_input::*;
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Key(KeyEvent),
|
Key(KeyEvent),
|
||||||
Mouse(MouseEvent),
|
|
||||||
FocusGained,
|
FocusGained,
|
||||||
FocusLost,
|
FocusLost,
|
||||||
}
|
}
|
||||||
@@ -46,20 +45,8 @@ pub enum KeyEvent {
|
|||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
impl From<KeyEvent> for Event {
|
||||||
pub enum MouseEvent {
|
fn from(value: KeyEvent) -> Self {
|
||||||
Press(MouseButton, u16, u16),
|
Self::Key(value)
|
||||||
Release(u16, u16),
|
}
|
||||||
Hold(u16, u16),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum MouseButton {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Middle,
|
|
||||||
WheelUp,
|
|
||||||
WheelDown,
|
|
||||||
WheelLeft,
|
|
||||||
WheelRight,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const TIOCGWINSZ: c_ulong = 0x4008_7468;
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
const NCCS: usize = 0x14;
|
const NCCS: usize = 0x14;
|
||||||
|
|
||||||
//
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default, Debug, Clone, Copy)]
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
struct Winsize {
|
struct Winsize {
|
||||||
|
|||||||
@@ -138,146 +138,10 @@ where
|
|||||||
Some(Ok(b'H')) => Some(Event::Key(KeyEvent::Home)),
|
Some(Ok(b'H')) => Some(Event::Key(KeyEvent::Home)),
|
||||||
Some(Ok(b'F')) => Some(Event::Key(KeyEvent::End)),
|
Some(Ok(b'F')) => Some(Event::Key(KeyEvent::End)),
|
||||||
Some(Ok(b'Z')) => Some(Event::Key(KeyEvent::BackTab)),
|
Some(Ok(b'Z')) => Some(Event::Key(KeyEvent::BackTab)),
|
||||||
Some(Ok(b'M')) => try_parse_x10_mouse(iter),
|
|
||||||
Some(Ok(b'<')) => try_parse_xterm_mouse(iter),
|
|
||||||
Some(Ok(c @ b'0'..=b'9')) => try_parse_rxvt_mouse(c, iter),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_parse_x10_mouse<I>(iter: &mut I) -> Option<Event>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = io::Result<u8>>,
|
|
||||||
{
|
|
||||||
let cb = iter.next()?.ok()? - 32;
|
|
||||||
|
|
||||||
let cx = u16::from(iter.next()?.ok()?.saturating_sub(33));
|
|
||||||
let cy = u16::from(iter.next()?.ok()?.saturating_sub(33));
|
|
||||||
match cb & 0x11 {
|
|
||||||
0 => {
|
|
||||||
if cb & 0x40 != 0 {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(
|
|
||||||
MouseButton::WheelUp,
|
|
||||||
cx,
|
|
||||||
cy,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(MouseButton::Left, cx, cy)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
if cb & 0x40 != 0 {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(
|
|
||||||
MouseButton::WheelDown,
|
|
||||||
cx,
|
|
||||||
cy,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(MouseButton::Middle, cx, cy)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
if cb & 0x40 != 0 {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(
|
|
||||||
MouseButton::WheelLeft,
|
|
||||||
cx,
|
|
||||||
cy,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(MouseButton::Right, cx, cy)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3 => {
|
|
||||||
if cb & 0x40 != 0 {
|
|
||||||
Some(Event::Mouse(MouseEvent::Press(
|
|
||||||
MouseButton::WheelRight,
|
|
||||||
cx,
|
|
||||||
cy,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Some(Event::Mouse(MouseEvent::Release(cx, cy)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_parse_xterm_mouse<I>(iter: &mut I) -> Option<Event>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = io::Result<u8>>,
|
|
||||||
{
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
let mut character = iter.next()?.ok()?;
|
|
||||||
while !matches!(character, b'm' | b'M') {
|
|
||||||
buf.push(character);
|
|
||||||
character = iter.next()?.ok()?;
|
|
||||||
}
|
|
||||||
let str_buf = String::from_utf8(buf).ok()?;
|
|
||||||
let nums = &mut str_buf.split(';');
|
|
||||||
|
|
||||||
let cb = nums.next()?.parse::<u16>().ok()?;
|
|
||||||
|
|
||||||
let cx = nums.next()?.parse::<u16>().ok()?;
|
|
||||||
let cy = nums.next()?.parse::<u16>().ok()?;
|
|
||||||
|
|
||||||
let event = match cb {
|
|
||||||
0..=2 | 64..=67 => {
|
|
||||||
let button = match cb {
|
|
||||||
0 => MouseButton::Left,
|
|
||||||
1 => MouseButton::Middle,
|
|
||||||
2 => MouseButton::Right,
|
|
||||||
64 => MouseButton::WheelUp,
|
|
||||||
65 => MouseButton::WheelDown,
|
|
||||||
66 => MouseButton::WheelLeft,
|
|
||||||
67 => MouseButton::WheelRight,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
match character {
|
|
||||||
b'M' => MouseEvent::Press(button, cx, cy),
|
|
||||||
b'm' => MouseEvent::Release(cx, cy),
|
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32 | 3 => MouseEvent::Hold(cx, cy),
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
Some(Event::Mouse(event))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_parse_rxvt_mouse<I>(c: u8, iter: &mut I) -> Option<Event>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = io::Result<u8>>,
|
|
||||||
{
|
|
||||||
let mut buf = vec![c];
|
|
||||||
let mut c = iter.next()?.ok()?;
|
|
||||||
while !(64..=126).contains(&c) {
|
|
||||||
buf.push(c);
|
|
||||||
c = iter.next()?.ok()?;
|
|
||||||
}
|
|
||||||
if c == b'M' {
|
|
||||||
let str_buf = String::from_utf8(buf).ok()?;
|
|
||||||
|
|
||||||
let nums: Vec<u16> = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
|
|
||||||
|
|
||||||
let cb = nums[0];
|
|
||||||
let cx = nums[1];
|
|
||||||
let cy = nums[2];
|
|
||||||
|
|
||||||
let event = match cb {
|
|
||||||
32 => MouseEvent::Press(MouseButton::Left, cx, cy),
|
|
||||||
33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
|
|
||||||
34 => MouseEvent::Press(MouseButton::Right, cx, cy),
|
|
||||||
35 => MouseEvent::Release(cx, cy),
|
|
||||||
64 => MouseEvent::Hold(cx, cy),
|
|
||||||
96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Some(Event::Mouse(event));
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_utf8() {
|
fn test_parse_utf8() {
|
||||||
let string = "abcéŷ¤£€ù%323";
|
let string = "abcéŷ¤£€ù%323";
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::io::{self, Stdin, Stdout};
|
use std::io;
|
||||||
use std::os::windows::io::RawHandle;
|
|
||||||
|
|
||||||
unsafe extern "system" {
|
unsafe extern "system" {
|
||||||
fn GetStdHandle(std_handle: u32) -> usize;
|
fn GetStdHandle(std_handle: u32) -> usize;
|
||||||
|
|||||||
@@ -13,19 +13,27 @@ struct InputRecord {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
union EventRecord {
|
union EventRecord {
|
||||||
key_event: KeyEventRecord,
|
key: KeyEventRecord,
|
||||||
mouse_event: MouseEventRecord,
|
focus: FocusEventRecord,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct KeyEventRecord {
|
struct KeyEventRecord {
|
||||||
key_down: i32,
|
key_down: i32,
|
||||||
|
repeat_count: u16,
|
||||||
virtual_key_code: u16,
|
virtual_key_code: u16,
|
||||||
|
virtual_scan_code: u16,
|
||||||
u_char: CharUnion,
|
u_char: CharUnion,
|
||||||
control_key_state: u32,
|
control_key_state: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct FocusEventRecord {
|
||||||
|
set_focus: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
union CharUnion {
|
union CharUnion {
|
||||||
@@ -33,34 +41,16 @@ union CharUnion {
|
|||||||
ascii_char: u8,
|
ascii_char: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct MouseEventRecord {
|
|
||||||
mouse_position: Coord,
|
|
||||||
button_state: u32,
|
|
||||||
control_key_state: u32,
|
|
||||||
event_flags: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct Coord {
|
|
||||||
x: i16,
|
|
||||||
y: i16,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "system" {
|
unsafe extern "system" {
|
||||||
fn ReadConsoleInputW(
|
fn ReadConsoleInputW(
|
||||||
h_console_input: usize,
|
console_input: usize,
|
||||||
lp_buffer: *mut InputRecord,
|
buffer: *mut InputRecord,
|
||||||
n_length: u32,
|
length: u32,
|
||||||
lp_number_of_events_read: *mut u32,
|
number_of_events_read: *mut u32,
|
||||||
) -> i32;
|
) -> i32;
|
||||||
fn WaitForMultipleObjects(
|
fn WaitForSingleObject(
|
||||||
n_count: u32,
|
handle: usize,
|
||||||
lp_handles: *mut usize,
|
wait_time_ms: u32,
|
||||||
b_wait_all: i32,
|
|
||||||
dw_wait_time: u32,
|
|
||||||
) -> u32;
|
) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +60,7 @@ pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
|||||||
let mut read = 0;
|
let mut read = 0;
|
||||||
|
|
||||||
let wait_time_millis = timeout.as_millis() as u32;
|
let wait_time_millis = timeout.as_millis() as u32;
|
||||||
let mut handles = [handle];
|
let result = unsafe { WaitForSingleObject(handle, wait_time_millis) };
|
||||||
let result = unsafe { WaitForMultipleObjects(1, handles.as_mut_ptr(), 0, wait_time_millis) };
|
|
||||||
|
|
||||||
// The function timed out
|
// The function timed out
|
||||||
if result != 0 {
|
if result != 0 {
|
||||||
@@ -83,14 +72,21 @@ pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
|||||||
if result == 0 {
|
if result == 0 {
|
||||||
return Err(io::Error::last_os_error())?;
|
return Err(io::Error::last_os_error())?;
|
||||||
}
|
}
|
||||||
if record.event_type == 1 {
|
match record.event_type {
|
||||||
let key_event = unsafe { record.event.key_event };
|
0x10 => { // Focus Event
|
||||||
if key_event.key_down == 0 {
|
Err(io::ErrorKind::InvalidData.into())
|
||||||
return Ok(Event::Key(KeyEvent::Null));
|
},
|
||||||
|
0x1 => { // Key Event
|
||||||
|
let key_event: KeyEventRecord = unsafe { record.event.key };
|
||||||
|
if key_event.key_down == 0 {
|
||||||
|
return Ok(Event::Key(KeyEvent::Null));
|
||||||
|
}
|
||||||
|
Ok(Event::Key(parse_key_event(&key_event)))
|
||||||
|
},
|
||||||
|
_ => { //TODO Make this better
|
||||||
|
Err(io::ErrorKind::InvalidData.into())
|
||||||
}
|
}
|
||||||
return Ok(Event::Key(parse_key_event(&key_event)));
|
|
||||||
}
|
}
|
||||||
Err(io::ErrorKind::InvalidData.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_key_event(event: &KeyEventRecord) -> KeyEvent {
|
fn parse_key_event(event: &KeyEventRecord) -> KeyEvent {
|
||||||
|
|||||||
Reference in New Issue
Block a user