Compare commits
2 Commits
c2e202a743
...
4d3c84596d
Author | SHA1 | Date |
---|---|---|
mars | 4d3c84596d | |
mars | 12b3bf2f14 |
139
src/main.rs
139
src/main.rs
|
@ -8,34 +8,45 @@ use alacritty_terminal::sync::FairMutex;
|
|||
use alacritty_terminal::term::color::{Colors, Rgb};
|
||||
use alacritty_terminal::tty::Pty;
|
||||
use alacritty_terminal::Term;
|
||||
use mio_extras::channel::Sender;
|
||||
use mio_extras::channel::Sender as MioSender;
|
||||
use softbuffer::GraphicsContext;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
use std::thread::JoinHandle;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
const WINDOW_WIDTH: usize = 900;
|
||||
const WINDOW_HEIGHT: usize = 600;
|
||||
|
||||
static FONT_DATA: &[u8] = include_bytes!("/usr/share/fonts/local/TamzenForPowerline10x20r.bdf");
|
||||
|
||||
pub struct TermListener {}
|
||||
pub struct TermListener {
|
||||
sender: Sender<TermEvent>,
|
||||
}
|
||||
|
||||
impl TermListener {
|
||||
pub fn new(sender: Sender<TermEvent>) -> Self {
|
||||
Self { sender }
|
||||
}
|
||||
}
|
||||
|
||||
impl EventListener for TermListener {
|
||||
fn send_event(&self, event: TermEvent) {}
|
||||
fn send_event(&self, event: TermEvent) {
|
||||
self.sender.send(event).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
font: bdf::Font,
|
||||
graphics: GraphicsContext<Window>,
|
||||
should_quit: bool,
|
||||
cell_width: usize,
|
||||
cell_height: usize,
|
||||
colors: Colors,
|
||||
term_loop: JoinHandle<(TermEventLoop<Pty, TermListener>, TermState)>,
|
||||
term_channel: Sender<TermMsg>,
|
||||
term_channel: MioSender<TermMsg>,
|
||||
term_events: Receiver<TermEvent>,
|
||||
term: Arc<FairMutex<Term<TermListener>>>,
|
||||
}
|
||||
|
||||
|
@ -47,8 +58,8 @@ impl App {
|
|||
let cell_height = font.bounds().height as usize;
|
||||
|
||||
let term_size = alacritty_terminal::term::SizeInfo::new(
|
||||
WINDOW_WIDTH as f32,
|
||||
WINDOW_HEIGHT as f32,
|
||||
2000.0,
|
||||
2000.0,
|
||||
cell_width as f32,
|
||||
cell_height as f32,
|
||||
0.0,
|
||||
|
@ -56,26 +67,34 @@ impl App {
|
|||
false,
|
||||
);
|
||||
|
||||
let term_config = Default::default();
|
||||
let term_events = TermListener {};
|
||||
let (sender, term_events) = channel();
|
||||
|
||||
let pty_config = PtyConfig {
|
||||
shell: Some(alacritty_terminal::config::Program::Just(
|
||||
"/usr/bin/fish".to_string(),
|
||||
)),
|
||||
working_directory: None,
|
||||
hold: false,
|
||||
let mut env = HashMap::<String, String>::default();
|
||||
env.insert("TERM".to_string(), "xterm".to_string());
|
||||
|
||||
let term_config = alacritty_terminal::config::Config {
|
||||
env,
|
||||
pty_config: PtyConfig {
|
||||
shell: Some(alacritty_terminal::config::Program::Just(
|
||||
"/usr/bin/fish".to_string(),
|
||||
)),
|
||||
working_directory: None,
|
||||
hold: false,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let term = Term::new(&term_config, term_size, term_events);
|
||||
let term_listener = TermListener::new(sender.clone());
|
||||
|
||||
let term = Term::new(&term_config, term_size, term_listener);
|
||||
let mut colors = term.colors().to_owned();
|
||||
let term = FairMutex::new(term);
|
||||
let term = Arc::new(term);
|
||||
|
||||
let pty = alacritty_terminal::tty::new(&pty_config, &term_size, None).unwrap();
|
||||
let pty = alacritty_terminal::tty::new(&term_config.pty_config, &term_size, None).unwrap();
|
||||
|
||||
let term_events = TermListener {};
|
||||
let term_loop = TermEventLoop::new(term.clone(), term_events, pty, false, false);
|
||||
let term_listener = TermListener::new(sender);
|
||||
let term_loop = TermEventLoop::new(term.clone(), term_listener, pty, false, false);
|
||||
let term_channel = term_loop.channel();
|
||||
|
||||
Self::load_colors(&mut colors);
|
||||
|
@ -83,15 +102,21 @@ impl App {
|
|||
Self {
|
||||
font,
|
||||
graphics: unsafe { GraphicsContext::new(window).unwrap() },
|
||||
should_quit: false,
|
||||
cell_width,
|
||||
cell_height,
|
||||
term,
|
||||
term_channel,
|
||||
term_events,
|
||||
colors,
|
||||
term_loop: term_loop.spawn(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_quit(&self) -> bool {
|
||||
self.should_quit
|
||||
}
|
||||
|
||||
pub fn load_colors(color: &mut Colors) {
|
||||
use NamedColor::*;
|
||||
|
||||
|
@ -157,23 +182,19 @@ impl App {
|
|||
}
|
||||
|
||||
pub fn redraw(&mut self) {
|
||||
/*let (width, height) = {
|
||||
let (width, height) = {
|
||||
let size = self.graphics.window().inner_size();
|
||||
(size.width as usize, size.height as usize)
|
||||
};*/
|
||||
|
||||
let (width, height) = (WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
};
|
||||
|
||||
let mut buffer = vec![0u32; (width * height) as usize];
|
||||
let term = self.term.lock();
|
||||
let content = term.renderable_content();
|
||||
|
||||
let mut fg_num = 0;
|
||||
let mut missing_chars = std::collections::HashSet::new();
|
||||
|
||||
for cell in content.display_iter.into_iter() {
|
||||
if let Some(glyph) = self.font.glyphs().get(&cell.c) {
|
||||
// println!("cell: {:?}", cell);
|
||||
|
||||
let term_row = cell.point.line.0 as usize;
|
||||
let term_col = cell.point.column.0 as usize;
|
||||
|
||||
|
@ -182,7 +203,11 @@ impl App {
|
|||
|
||||
let mut px_row = term_row * width * self.cell_height;
|
||||
|
||||
if px_row >= buffer.len() {
|
||||
if (term_row + 1) * self.cell_height > height {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (term_col + 1) * self.cell_width > width {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -190,27 +215,22 @@ impl App {
|
|||
let px_start = px_row + term_col * self.cell_width;
|
||||
for x in 0..self.cell_width {
|
||||
let color = if glyph.get(x as u32, y as u32) {
|
||||
fg_num += 1;
|
||||
fg
|
||||
} else {
|
||||
bg
|
||||
};
|
||||
|
||||
let off = px_start + x as usize;
|
||||
|
||||
// if off < buffer.len() {
|
||||
buffer[off] = color;
|
||||
// }
|
||||
buffer[px_start + x as usize] = color;
|
||||
}
|
||||
|
||||
px_row += width;
|
||||
}
|
||||
} else {
|
||||
println!("missing char: {}", cell.c);
|
||||
missing_chars.insert(cell.c);
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("FG num: {}", fg_num);
|
||||
log::debug!("Missing characters: {:?}", missing_chars);
|
||||
|
||||
self.graphics
|
||||
.set_buffer(&buffer, width as u16, height as u16);
|
||||
|
@ -230,19 +250,45 @@ impl App {
|
|||
((rgb.r as u32) << 16) | ((rgb.g as u32) << 8) | (rgb.b as u32)
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {}
|
||||
pub fn update(&mut self) {
|
||||
while let Ok(event) = self.term_events.try_recv() {
|
||||
match event {
|
||||
TermEvent::Exit => self.should_quit = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_keyboard_input(&mut self, input: &winit::event::KeyboardInput) {
|
||||
if input.state == winit::event::ElementState::Pressed {
|
||||
if let Some(keycode) = input.virtual_keycode {
|
||||
if let Some(c) = virtual_keycode_to_byte(keycode) {
|
||||
let bytes = [c];
|
||||
let cow = Cow::Owned(bytes.into());
|
||||
self.term_channel.send(TermMsg::Input(cow)).unwrap();
|
||||
self.on_received_character(c as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_received_character(&mut self, c: char) {
|
||||
let mut bytes = [0u8; 4];
|
||||
let len = c.encode_utf8(&mut bytes).len();
|
||||
let cow = Cow::Owned(bytes[0..len].into());
|
||||
self.term_channel.send(TermMsg::Input(cow)).unwrap();
|
||||
}
|
||||
|
||||
pub fn on_resize(&mut self, width: u32, height: u32) {
|
||||
let term_size = alacritty_terminal::term::SizeInfo::new(
|
||||
width as f32,
|
||||
height as f32,
|
||||
self.cell_width as f32,
|
||||
self.cell_height as f32,
|
||||
0.0,
|
||||
0.0,
|
||||
false,
|
||||
);
|
||||
|
||||
self.term_channel.send(TermMsg::Resize(term_size)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn virtual_keycode_to_byte(keycode: winit::event::VirtualKeyCode) -> Option<u8> {
|
||||
|
@ -326,13 +372,20 @@ fn main() {
|
|||
WindowEvent::CloseRequested => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
WindowEvent::KeyboardInput { input, .. } => {
|
||||
app.on_keyboard_input(&input);
|
||||
WindowEvent::ReceivedCharacter(c) => {
|
||||
app.on_received_character(c);
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
app.on_resize(size.width, size.height);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if app.should_quit() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue