inhouse pty
This commit is contained in:
@@ -7,6 +7,6 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ming-wm-lib = { path = "../ming-wm-lib" }
|
||||
linux = { path = "linux" }
|
||||
linux = { path = "../linux" }
|
||||
bitcoin_hashes = { version = "0.16.0", default-features = false }
|
||||
bmp-rust = "0.5.0"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "linux"
|
||||
version = "0.1.0"
|
||||
license = "GPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
@@ -1,146 +0,0 @@
|
||||
use std::fs::{ File, OpenOptions };
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{ ioctl, mmap, munmap, c_ulong, c_int };
|
||||
|
||||
//https://stackoverflow.com/a/75402838
|
||||
|
||||
//https://github.com/torvalds/linux/blob/master/include/uapi/linux/fb.h
|
||||
const FBIOGET_VSCREENINFO: c_ulong = 0x4600;
|
||||
const FBIOGET_FSCREENINFO: c_ulong = 0x4602;
|
||||
|
||||
//https://www.kernel.org/doc/html/latest/fb/api.html
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
pub struct FB_BITFIELD {
|
||||
offset: u32,
|
||||
length: u32,
|
||||
msb_right: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
pub struct FB_VAR_SCREENINFO {
|
||||
pub xres: u32,
|
||||
pub yres: u32,
|
||||
pub xres_virtual: u32,
|
||||
pub yres_virtual: u32,
|
||||
pub xoffset: u32,
|
||||
pub yoffset: u32,
|
||||
pub bits_per_pixel: u32,
|
||||
pub grayscale: u32,
|
||||
pub red: FB_BITFIELD,
|
||||
pub green: FB_BITFIELD,
|
||||
pub blue: FB_BITFIELD,
|
||||
pub transp: FB_BITFIELD,
|
||||
pub nonstd: u32,
|
||||
pub activate: u32,
|
||||
pub height: u32,
|
||||
pub width: u32,
|
||||
pub accel_flags: u32,
|
||||
pub pixclock: u32,
|
||||
pub left_margin: u32,
|
||||
pub right_margin: u32,
|
||||
pub upper_margin: u32,
|
||||
pub lower_margin: u32,
|
||||
pub hsync_len: u32,
|
||||
pub wsync_len: u32,
|
||||
pub sync: u32,
|
||||
pub vmode: u32,
|
||||
pub rotate: u32,
|
||||
pub colorspace: u32,
|
||||
pub reserved: [u32; 4],
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
pub struct FB_FIX_SCREENINFO {
|
||||
pub id: [u8; 16],
|
||||
pub smem_start: usize,
|
||||
pub smem_len: u32,
|
||||
pub r#type: u32,
|
||||
pub type_aux: u32,
|
||||
pub visual: u32,
|
||||
pub xpanstep: u16,
|
||||
pub ypanstep: u16,
|
||||
pub ywrapstep: u16,
|
||||
pub line_length: u32,
|
||||
pub mmio_len: u32,
|
||||
pub accel: u32,
|
||||
pub capabilities: u16,
|
||||
pub reserved: [u16; 2],
|
||||
}
|
||||
|
||||
pub struct Framebuffer {
|
||||
pointer: *mut libc::c_void,
|
||||
pub var_screen_info: FB_VAR_SCREENINFO,
|
||||
pub fix_screen_info: FB_FIX_SCREENINFO,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl Framebuffer {
|
||||
pub fn open(path: &str) -> Result<Self, ()> {
|
||||
let file = Framebuffer::open_file(path)?;
|
||||
let vi = Framebuffer::get_vscreeninfo(file.as_raw_fd())?;
|
||||
let fi = Framebuffer::get_fscreeninfo(file.as_raw_fd())?;
|
||||
//then mmap or something
|
||||
let size = vi.yres_virtual * fi.line_length * (vi.bits_per_pixel / 8);
|
||||
let pointer = unsafe {
|
||||
mmap(ptr::null_mut(), size.try_into().unwrap(), libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, file.as_raw_fd(), 0)
|
||||
};
|
||||
if pointer == libc::MAP_FAILED {
|
||||
return Err(());
|
||||
}
|
||||
Ok(Self {
|
||||
pointer,
|
||||
var_screen_info: vi,
|
||||
fix_screen_info: fi,
|
||||
size: size as usize,
|
||||
})
|
||||
}
|
||||
|
||||
fn open_file(path: &str) -> Result<File, ()> {
|
||||
OpenOptions::new().read(true).write(true).open(path).map_err(|_| ())
|
||||
}
|
||||
|
||||
fn get_vscreeninfo(raw_fd: c_int) -> Result<FB_VAR_SCREENINFO, ()> {
|
||||
let mut vi: FB_VAR_SCREENINFO = Default::default();
|
||||
let result = unsafe {
|
||||
ioctl(raw_fd, FBIOGET_VSCREENINFO.try_into().unwrap(), &mut vi)
|
||||
};
|
||||
if result != -1 {
|
||||
Ok(vi)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fscreeninfo(raw_fd: c_int) -> Result<FB_FIX_SCREENINFO, ()> {
|
||||
let mut fi: FB_FIX_SCREENINFO = Default::default();
|
||||
let result = unsafe {
|
||||
ioctl(raw_fd, FBIOGET_FSCREENINFO.try_into().unwrap(), &mut fi)
|
||||
};
|
||||
if result != -1 {
|
||||
Ok(fi)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_frame(&mut self, frame: &[u8]) {
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(frame.as_ptr(), self.pointer as *mut u8, frame.len());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Framebuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
munmap(self.pointer, self.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
use std::io::{ Read, Stdin };
|
||||
use std::sync::mpsc::{ channel, Receiver };
|
||||
use std::thread;
|
||||
|
||||
//includes a section on reading keys
|
||||
//https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html
|
||||
|
||||
const ALPHABET: [char; 26] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
|
||||
|
||||
pub enum Key {
|
||||
Char(char),
|
||||
Alt(char),
|
||||
Ctrl(char),
|
||||
Backspace,
|
||||
Esc,
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
Other(u8), //we don't get about anything else, lmao
|
||||
}
|
||||
|
||||
pub struct RawStdin {
|
||||
//bytes: Peekable<Bytes<StdinLock<'a>>>,
|
||||
receiver: Receiver<u8>,
|
||||
}
|
||||
|
||||
impl RawStdin {
|
||||
pub fn new(stdin: Stdin) -> Self {
|
||||
let (sender, receiver) = channel();
|
||||
thread::spawn(move || {
|
||||
let bytes = stdin.lock().bytes();
|
||||
for b in bytes {
|
||||
sender.send(b.unwrap()).unwrap();
|
||||
}
|
||||
});
|
||||
RawStdin {
|
||||
//bytes: stdin.lock().bytes().peekable(),
|
||||
receiver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for RawStdin {
|
||||
type Item = Key;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let first = self.receiver.recv().unwrap();
|
||||
Some(match first {
|
||||
1..=26 => {
|
||||
//ctrl
|
||||
if first == 9 {
|
||||
Key::Char('\t')
|
||||
} else if first == 13 {
|
||||
//ctrl+m and enter give the same thing
|
||||
Key::Char('\n')
|
||||
} else {
|
||||
Key::Ctrl(ALPHABET[first as usize - 1])
|
||||
}
|
||||
},
|
||||
27 => {
|
||||
//escape sequence
|
||||
//not handling escape sequences that are 3+ bytes is probably going to come back to bite us
|
||||
let n = self.receiver.try_recv();
|
||||
if let Ok(b'[') = n {
|
||||
let n = self.receiver.recv().unwrap();
|
||||
match n {
|
||||
b'A' => Key::ArrowUp,
|
||||
b'B' => Key::ArrowDown,
|
||||
b'C' => Key::ArrowRight,
|
||||
b'D' => Key::ArrowLeft,
|
||||
_ => Key::Other(n),
|
||||
}
|
||||
} else if n.is_ok() {
|
||||
//Alt+<char> sends Esc+<char>
|
||||
Key::Alt(char::from(n.unwrap()))
|
||||
} else {
|
||||
Key::Esc
|
||||
}
|
||||
},
|
||||
127 => {
|
||||
Key::Backspace
|
||||
},
|
||||
_ => {
|
||||
Key::Char(char::from(first))
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod fb;
|
||||
pub mod raw;
|
||||
pub mod keys;
|
||||
@@ -1,65 +0,0 @@
|
||||
use std::io::Stdout;
|
||||
use std::mem::zeroed;
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
use libc::{ cfmakeraw, c_int, tcgetattr, tcsetattr, termios, TCSAFLUSH };
|
||||
|
||||
//https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html
|
||||
//on TCSAFLUSH: "The TCSAFLUSH argument specifies when to apply the change: in this case, it waits for all pending output to be written to the terminal, and also discards any input that hasn't been read."
|
||||
|
||||
//https://www.man7.org/linux/man-pages/man3/termios.3.html
|
||||
//(use cfmakeraw instead doing all those bitwise stuff manually)
|
||||
|
||||
//enter and exit tty raw mode
|
||||
|
||||
pub struct RawStdout {
|
||||
pub stdout: Stdout,
|
||||
old_termios: termios,
|
||||
}
|
||||
|
||||
impl RawStdout {
|
||||
pub fn new(stdout: Stdout) -> Self {
|
||||
RawStdout {
|
||||
stdout,
|
||||
old_termios: unsafe { zeroed() },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_termios(raw_fd: c_int) -> Result<termios, ()> {
|
||||
let mut termios_struct: termios = unsafe { zeroed() };
|
||||
let result = unsafe {
|
||||
tcgetattr(raw_fd, &mut termios_struct)
|
||||
};
|
||||
if result != -1 {
|
||||
Ok(termios_struct)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_raw_mode(&mut self) -> Result<(), ()> {
|
||||
let raw_fd = self.stdout.as_raw_fd();
|
||||
let mut termios_struct = Self::get_termios(raw_fd)?;
|
||||
self.old_termios = termios_struct;
|
||||
let result = unsafe {
|
||||
cfmakeraw(&mut termios_struct);
|
||||
tcsetattr(raw_fd, TCSAFLUSH, &mut termios_struct)
|
||||
};
|
||||
if result != -1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit_raw_mode(&mut self) -> Result<(), ()> {
|
||||
let result = unsafe {
|
||||
tcsetattr(self.stdout.as_raw_fd(), TCSAFLUSH, &mut self.old_termios)
|
||||
};
|
||||
if result != -1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user