Compare commits
2 Commits
b836cf7fc7
...
de16799908
Author | SHA1 | Date | |
---|---|---|---|
de16799908 | |||
250d70a958 |
@ -134,15 +134,15 @@ table! {
|
||||
pub static CODE_SET_1_E0: [Key; 128; Key::Unknown] = [
|
||||
0x1D => Key::RControl,
|
||||
0x38 => Key::RAlt,
|
||||
// 0x47 => Key::Home,
|
||||
// 0x48 => Key::Up,
|
||||
// 0x49 => Key::PageUp,
|
||||
// 0x4B => Key::Left,
|
||||
// 0x4D => Key::Right,
|
||||
// 0x4F => Key::End,
|
||||
// 0x50 => Key::Down,
|
||||
// 0x51 => Key::PageDown,
|
||||
// 0x52 => Key::Insert,
|
||||
// 0x53 => Key::Delete,
|
||||
0x47 => Key::Home,
|
||||
0x48 => Key::Up,
|
||||
0x49 => Key::PageUp,
|
||||
0x4B => Key::Left,
|
||||
0x4D => Key::Right,
|
||||
0x4F => Key::End,
|
||||
0x50 => Key::Down,
|
||||
0x51 => Key::PageDown,
|
||||
0x52 => Key::Insert,
|
||||
0x53 => Key::Delete,
|
||||
];
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ impl InterruptHandler for PS2Controller {
|
||||
fn handle_irq(self: Arc<Self>, _vector: IrqVector) -> bool {
|
||||
let mut count = 0;
|
||||
let mut inner = self.inner.lock();
|
||||
let mut e0 = false;
|
||||
|
||||
loop {
|
||||
let Some(mut scancode) = inner.try_recv() else {
|
||||
@ -87,7 +88,10 @@ impl InterruptHandler for PS2Controller {
|
||||
|
||||
count += 1;
|
||||
|
||||
let e0 = scancode == 0xE0;
|
||||
if scancode == 0xE0 {
|
||||
e0 = true;
|
||||
continue;
|
||||
}
|
||||
let release = scancode >= 0x80;
|
||||
|
||||
if release {
|
||||
@ -101,6 +105,8 @@ impl InterruptHandler for PS2Controller {
|
||||
KeyboardKeyEvent::Pressed(key)
|
||||
};
|
||||
|
||||
e0 = false;
|
||||
|
||||
ygg_driver_input::send_event(event);
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,22 @@ pub enum KeyboardKey {
|
||||
RShift,
|
||||
LControl,
|
||||
RControl,
|
||||
PageUp,
|
||||
PageDown,
|
||||
LAlt,
|
||||
RAlt,
|
||||
CapsLock,
|
||||
Escape,
|
||||
Backspace,
|
||||
Tab,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Home,
|
||||
End,
|
||||
Insert,
|
||||
Delete,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@ -54,6 +64,16 @@ impl KeyboardKey {
|
||||
// 0x98: Escape
|
||||
// 0x99: Backspace
|
||||
// 0x9A: Tab
|
||||
// 0xA0: PageUp
|
||||
// 0xA1: PageDown
|
||||
// 0xA2: Up
|
||||
// 0xA3: Down
|
||||
// 0xA4: Left
|
||||
// 0xA5: Right
|
||||
// 0xA6: Home
|
||||
// 0xA7: End
|
||||
// 0xA8: Insert
|
||||
// 0xA9: Delete
|
||||
// 0xFF: Unknown
|
||||
KeyboardKeyCode(match self {
|
||||
Self::Char(b) => b as u16,
|
||||
@ -69,6 +89,16 @@ impl KeyboardKey {
|
||||
Self::Escape => 0x98,
|
||||
Self::Backspace => 0x99,
|
||||
Self::Tab => 0x9A,
|
||||
Self::PageUp => 0xA0,
|
||||
Self::PageDown => 0xA1,
|
||||
Self::Up => 0xA2,
|
||||
Self::Down => 0xA3,
|
||||
Self::Left => 0xA4,
|
||||
Self::Right => 0xA5,
|
||||
Self::Home => 0xA6,
|
||||
Self::End => 0xA7,
|
||||
Self::Insert => 0xA8,
|
||||
Self::Delete => 0xA9,
|
||||
Self::Unknown => 0xFF,
|
||||
})
|
||||
}
|
||||
@ -93,6 +123,16 @@ impl KeyboardKey {
|
||||
0x98 => Self::Escape,
|
||||
0x99 => Self::Backspace,
|
||||
0x9A => Self::Tab,
|
||||
0xA0 => Self::PageUp,
|
||||
0xA1 => Self::PageDown,
|
||||
0xA2 => Self::Up,
|
||||
0xA3 => Self::Down,
|
||||
0xA4 => Self::Left,
|
||||
0xA5 => Self::Right,
|
||||
0xA6 => Self::Home,
|
||||
0xA7 => Self::End,
|
||||
0xA8 => Self::Insert,
|
||||
0xA9 => Self::Delete,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
|
@ -85,12 +85,15 @@ impl DrawState {
|
||||
dt.fill(default_bg);
|
||||
}
|
||||
|
||||
|
||||
if cursor_dirty {
|
||||
state.buffer.set_row_dirty(self.old_cursor.row);
|
||||
}
|
||||
|
||||
let bytes_per_line = (self.font.width() as usize + 7) / 8;
|
||||
for (i, row) in state.buffer.dirty_rows() {
|
||||
let scroll = state.adjust_scroll();
|
||||
let cursor_visible = scroll == 0;
|
||||
state.buffer.visible_rows_mut(scroll, |i, row| {
|
||||
let cy = i * fh;
|
||||
|
||||
for (j, cell) in row.cells().enumerate() {
|
||||
@ -132,27 +135,32 @@ impl DrawState {
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// for (i, row) in state.buffer.dirty_rows() {
|
||||
// }
|
||||
|
||||
// TODO check if there's a character under cursor
|
||||
let cx = state.cursor.col * fw;
|
||||
let cy = state.cursor.row * fh;
|
||||
if cursor_visible {
|
||||
let cx = state.cursor.col * fw;
|
||||
let cy = state.cursor.row * fh;
|
||||
|
||||
// Fill block cursor
|
||||
for y in 0..fh {
|
||||
let off = (cy + y) * self.width + cx;
|
||||
dt[off..off + fw].fill(default_fg);
|
||||
}
|
||||
|
||||
if !self.focused {
|
||||
// Remove cursor center
|
||||
for y in 1..fh - 1 {
|
||||
let off = (cy + y) * self.width + cx + 1;
|
||||
dt[off..off + fw - 2].fill(default_bg);
|
||||
// Fill block cursor
|
||||
for y in 0..fh {
|
||||
let off = (cy + y) * self.width + cx;
|
||||
dt[off..off + fw].fill(default_fg);
|
||||
}
|
||||
|
||||
if !self.focused {
|
||||
// Remove cursor center
|
||||
for y in 1..fh - 1 {
|
||||
let off = (cy + y) * self.width + cx + 1;
|
||||
dt[off..off + fw - 2].fill(default_bg);
|
||||
}
|
||||
}
|
||||
|
||||
self.old_cursor = state.cursor;
|
||||
}
|
||||
|
||||
self.old_cursor = state.cursor;
|
||||
self.force_redraw = false;
|
||||
self.focus_changed = false;
|
||||
}
|
||||
@ -211,32 +219,56 @@ impl Terminal<'_> {
|
||||
EventOutcome::Redraw
|
||||
});
|
||||
|
||||
let state_c = state.clone();
|
||||
let pty_master_c = pty_master.clone();
|
||||
window.set_on_key_input(move |ev| {
|
||||
let mut s = state_c.lock().unwrap();
|
||||
let mut pty_master = pty_master_c.lock().unwrap();
|
||||
let mut need_redraw = false;
|
||||
|
||||
// TODO error reporting from handlers
|
||||
if let Some(input) = ev.input {
|
||||
pty_master.write_all(&[input as u8]).unwrap();
|
||||
need_redraw = s.scroll_end();
|
||||
} else {
|
||||
match (ev.modifiers, ev.key) {
|
||||
(KeyModifiers::NONE, KeyboardKey::Escape) => {
|
||||
pty_master.write_all(b"\x1B").unwrap();
|
||||
need_redraw = s.scroll_end();
|
||||
}
|
||||
(KeyModifiers::NONE, KeyboardKey::Backspace) => {
|
||||
pty_master.write_all(&[termios.chars.erase]).unwrap();
|
||||
need_redraw = s.scroll_end();
|
||||
}
|
||||
(KeyModifiers::CTRL, KeyboardKey::Char(b'c')) => {
|
||||
pty_master.write_all(&[termios.chars.interrupt]).unwrap();
|
||||
need_redraw = s.scroll_end();
|
||||
}
|
||||
(KeyModifiers::CTRL, KeyboardKey::Char(b'd')) => {
|
||||
pty_master.write_all(&[termios.chars.eof]).unwrap();
|
||||
need_redraw = s.scroll_end();
|
||||
}
|
||||
(KeyModifiers::SHIFT, KeyboardKey::PageUp) => {
|
||||
need_redraw = s.scroll_up();
|
||||
}
|
||||
(KeyModifiers::SHIFT, KeyboardKey::PageDown) => {
|
||||
need_redraw = s.scroll_down();
|
||||
}
|
||||
(KeyModifiers::SHIFT, KeyboardKey::Home) => {
|
||||
need_redraw = s.scroll_home();
|
||||
}
|
||||
(KeyModifiers::SHIFT, KeyboardKey::End) => {
|
||||
need_redraw = s.scroll_end();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
EventOutcome::None
|
||||
if need_redraw {
|
||||
EventOutcome::Redraw
|
||||
} else {
|
||||
EventOutcome::None
|
||||
}
|
||||
});
|
||||
|
||||
let draw_state_c = draw_state.clone();
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::attr::{CellAttributes, Color};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@ -13,9 +15,11 @@ pub struct GridRow {
|
||||
}
|
||||
|
||||
pub struct Buffer {
|
||||
scrollback: VecDeque<GridRow>,
|
||||
rows: Vec<GridRow>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
scrollback_limit: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
@ -36,6 +40,7 @@ pub struct State {
|
||||
esc_state: EscapeState,
|
||||
esc_args: Vec<u32>,
|
||||
|
||||
scroll: usize,
|
||||
pub cursor: Cursor,
|
||||
#[allow(unused)]
|
||||
saved_cursor: Option<Cursor>,
|
||||
@ -106,6 +111,8 @@ impl Buffer {
|
||||
pub fn new(width: usize, height: usize, bg: Color) -> Self {
|
||||
Self {
|
||||
rows: vec![GridRow::new(width, bg); height],
|
||||
scrollback: VecDeque::new(),
|
||||
scrollback_limit: 1024,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
@ -115,15 +122,30 @@ impl Buffer {
|
||||
self.rows.fill(GridRow::new(self.width, bg));
|
||||
}
|
||||
|
||||
pub fn dirty_rows(&mut self) -> impl Iterator<Item = (usize, &mut GridRow)> {
|
||||
self.rows.iter_mut().enumerate().filter_map(|(i, row)| {
|
||||
pub fn iter_rows_mut<F: FnMut(usize, &mut GridRow)>(&mut self, scroll: usize, mut handler: F) {
|
||||
let scroll = scroll.min(self.scrollback.len());
|
||||
let non_scroll = self.height.saturating_sub(scroll);
|
||||
let scroll_end = self.height - non_scroll;
|
||||
|
||||
for y in 0..scroll_end {
|
||||
let i = scroll - 1 - y;
|
||||
let row = &mut self.scrollback[i];
|
||||
handler(y, row);
|
||||
}
|
||||
for i in 0..non_scroll {
|
||||
let y = scroll + i;
|
||||
let row = &mut self.rows[i];
|
||||
handler(y, row);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visible_rows_mut<F: FnMut(usize, &mut GridRow)>(&mut self, scroll: usize, mut handler: F) {
|
||||
self.iter_rows_mut(scroll, |y, row| {
|
||||
if row.dirty {
|
||||
row.dirty = false;
|
||||
Some((i, row))
|
||||
} else {
|
||||
None
|
||||
handler(y, row);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, width: usize, height: usize, bg: Color) {
|
||||
@ -142,6 +164,11 @@ impl Buffer {
|
||||
}
|
||||
|
||||
pub fn scroll_once(&mut self, bg: Color) {
|
||||
self.scrollback.push_front(self.rows[0].clone());
|
||||
if self.scrollback.len() >= self.scrollback_limit {
|
||||
self.scrollback.pop_back();
|
||||
}
|
||||
|
||||
for i in 1..self.height {
|
||||
self.rows[i - 1] = self.rows[i].clone();
|
||||
self.rows[i - 1].dirty = true;
|
||||
@ -156,6 +183,10 @@ impl Buffer {
|
||||
pub fn set_row_dirty(&mut self, row: usize) {
|
||||
self.rows[row].dirty = true;
|
||||
}
|
||||
|
||||
pub fn invalidate_rows(&mut self, scroll: usize) {
|
||||
self.iter_rows_mut(scroll, |_, row| row.dirty = true);
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
@ -173,6 +204,7 @@ impl State {
|
||||
esc_state: EscapeState::Normal,
|
||||
|
||||
cursor: Cursor { row: 0, col: 0 },
|
||||
scroll: 0,
|
||||
saved_cursor: None,
|
||||
|
||||
default_attributes,
|
||||
@ -183,6 +215,7 @@ impl State {
|
||||
pub fn resize(&mut self, width: usize, height: usize) {
|
||||
self.buffer
|
||||
.resize(width, height, self.default_attributes.bg);
|
||||
self.scroll = 0;
|
||||
|
||||
if self.cursor.row >= height {
|
||||
self.cursor.row = height - 1;
|
||||
@ -370,4 +403,63 @@ impl State {
|
||||
EscapeState::Csi => self.handle_ctlseq_byte(ch),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invalidate_current_viewport(&mut self) {
|
||||
self.buffer.invalidate_rows(self.scroll);
|
||||
}
|
||||
|
||||
pub fn adjust_scroll(&mut self) -> usize {
|
||||
if self.scroll > self.buffer.scrollback.len() {
|
||||
self.scroll = self.buffer.scrollback.len();
|
||||
}
|
||||
|
||||
self.scroll
|
||||
}
|
||||
|
||||
pub fn scroll_up(&mut self) -> bool {
|
||||
let max = self.buffer.scrollback.len();
|
||||
if max == 0 {
|
||||
self.scroll = 0;
|
||||
return true;
|
||||
}
|
||||
let amount = max.min(8);
|
||||
if amount != 0 {
|
||||
self.scroll += amount;
|
||||
self.invalidate_current_viewport();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_down(&mut self) -> bool {
|
||||
let amount = self.scroll.min(8);
|
||||
if amount != 0 {
|
||||
self.scroll -= amount;
|
||||
self.invalidate_current_viewport();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_home(&mut self) -> bool {
|
||||
if self.scroll != self.buffer.scrollback.len() {
|
||||
self.scroll = self.buffer.scrollback.len();
|
||||
self.invalidate_current_viewport();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_end(&mut self) -> bool {
|
||||
if self.scroll != 0 {
|
||||
self.scroll = 0;
|
||||
self.invalidate_current_viewport();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user