Add scrollbar and scrolling
This commit is contained in:
parent
f6118a5cee
commit
ee3cc21ece
3 changed files with 62 additions and 23 deletions
|
|
@ -20,7 +20,7 @@ use cosmic::{
|
||||||
use std::{any::TypeId, sync::Mutex};
|
use std::{any::TypeId, sync::Mutex};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use self::terminal::Terminal;
|
use self::terminal::{Terminal, TerminalScroll};
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
|
||||||
use self::terminal_box::terminal_box;
|
use self::terminal_box::terminal_box;
|
||||||
|
|
@ -179,7 +179,7 @@ impl cosmic::Application for App {
|
||||||
self.tab_model.text_set(entity, title);
|
self.tab_model.text_set(entity, title);
|
||||||
return self.update_title();
|
return self.update_title();
|
||||||
}
|
}
|
||||||
TermEvent::Wakeup => {
|
TermEvent::MouseCursorDirty | TermEvent::Wakeup => {
|
||||||
if let Some(terminal) = self.tab_model.data::<Mutex<Terminal>>(entity) {
|
if let Some(terminal) = self.tab_model.data::<Mutex<Terminal>>(entity) {
|
||||||
let mut terminal = terminal.lock().unwrap();
|
let mut terminal = terminal.lock().unwrap();
|
||||||
terminal.update();
|
terminal.update();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use alacritty_terminal::{
|
use alacritty_terminal::{
|
||||||
ansi::{Color, NamedColor},
|
ansi::{Color, Handler, NamedColor},
|
||||||
config::{Config, PtyConfig},
|
config::{Config, PtyConfig},
|
||||||
event::{Event, EventListener, Notify, OnResize, WindowSize},
|
event::{Event, EventListener, Notify, OnResize, WindowSize},
|
||||||
event_loop::{EventLoop, Msg, Notifier, State},
|
event_loop::{EventLoop, Msg, Notifier, State},
|
||||||
|
|
@ -25,6 +25,8 @@ use std::{
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
pub use alacritty_terminal::grid::Scroll as TerminalScroll;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
width: u32,
|
width: u32,
|
||||||
|
|
@ -318,6 +320,22 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll(&self, scroll: TerminalScroll) {
|
||||||
|
self.term.lock().scroll_display(scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scrollbar(&self) -> (f32, f32) {
|
||||||
|
let term = self.term.lock();
|
||||||
|
let grid = term.grid();
|
||||||
|
let total = grid.history_size() + grid.screen_lines();
|
||||||
|
let start = total - grid.display_offset();
|
||||||
|
let end = total - (grid.display_offset() + grid.screen_lines());
|
||||||
|
(
|
||||||
|
(start as f32) / (total as f32),
|
||||||
|
(end as f32) / (total as f32),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) -> bool {
|
pub fn update(&mut self) -> bool {
|
||||||
let instant = Instant::now();
|
let instant = Instant::now();
|
||||||
|
|
||||||
|
|
@ -326,15 +344,15 @@ impl Terminal {
|
||||||
{
|
{
|
||||||
let mut buffer = Arc::make_mut(&mut self.buffer);
|
let mut buffer = Arc::make_mut(&mut self.buffer);
|
||||||
|
|
||||||
let mut last_point = Point::new(Line(0), Column(0));
|
let mut line_i = 0;
|
||||||
|
let mut last_point = None;
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
let mut attrs_list = AttrsList::new(self.default_attrs);
|
let mut attrs_list = AttrsList::new(self.default_attrs);
|
||||||
{
|
{
|
||||||
let term_guard = self.term.lock();
|
let term_guard = self.term.lock();
|
||||||
let grid = term_guard.grid();
|
let grid = term_guard.grid();
|
||||||
for indexed in grid.display_iter() {
|
for indexed in grid.display_iter() {
|
||||||
if indexed.point.line != last_point.line {
|
if indexed.point.line != last_point.unwrap_or(indexed.point).line {
|
||||||
let line_i = last_point.line.0 as usize;
|
|
||||||
while line_i >= buffer.lines.len() {
|
while line_i >= buffer.lines.len() {
|
||||||
buffer.lines.push(BufferLine::new(
|
buffer.lines.push(BufferLine::new(
|
||||||
"",
|
"",
|
||||||
|
|
@ -347,6 +365,7 @@ impl Terminal {
|
||||||
if buffer.lines[line_i].set_text(text.clone(), attrs_list.clone()) {
|
if buffer.lines[line_i].set_text(text.clone(), attrs_list.clone()) {
|
||||||
buffer.set_redraw(true);
|
buffer.set_redraw(true);
|
||||||
}
|
}
|
||||||
|
line_i += 1;
|
||||||
|
|
||||||
text.clear();
|
text.clear();
|
||||||
attrs_list.clear_spans();
|
attrs_list.clear_spans();
|
||||||
|
|
@ -389,12 +408,11 @@ impl Terminal {
|
||||||
attrs_list.add_span(start..end, attrs);
|
attrs_list.add_span(start..end, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_point = indexed.point;
|
last_point = Some(indexed.point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: do not repeat!
|
//TODO: do not repeat!
|
||||||
let line_i = last_point.line.0 as usize;
|
|
||||||
while line_i >= buffer.lines.len() {
|
while line_i >= buffer.lines.len() {
|
||||||
buffer.lines.push(BufferLine::new(
|
buffer.lines.push(BufferLine::new(
|
||||||
"",
|
"",
|
||||||
|
|
@ -407,9 +425,10 @@ impl Terminal {
|
||||||
if buffer.lines[line_i].set_text(text, attrs_list) {
|
if buffer.lines[line_i].set_text(text, attrs_list) {
|
||||||
buffer.set_redraw(true);
|
buffer.set_redraw(true);
|
||||||
}
|
}
|
||||||
|
line_i += 1;
|
||||||
|
|
||||||
if buffer.lines.len() != line_i + 1 {
|
if buffer.lines.len() != line_i {
|
||||||
buffer.lines.truncate(line_i + 1);
|
buffer.lines.truncate(line_i);
|
||||||
buffer.set_redraw(true);
|
buffer.set_redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Terminal;
|
use crate::{Terminal, TerminalScroll};
|
||||||
|
|
||||||
pub struct TerminalBox<'a, Message> {
|
pub struct TerminalBox<'a, Message> {
|
||||||
terminal: &'a Mutex<Terminal>,
|
terminal: &'a Mutex<Terminal>,
|
||||||
|
|
@ -183,7 +183,7 @@ where
|
||||||
let mut terminal = self.terminal.lock().unwrap();
|
let mut terminal = self.terminal.lock().unwrap();
|
||||||
|
|
||||||
//TODO: make this configurable
|
//TODO: make this configurable
|
||||||
let scrollbar_w = 0.0;
|
let scrollbar_w = 8.0;
|
||||||
|
|
||||||
let view_position =
|
let view_position =
|
||||||
layout.position() + [self.padding.left as f32, self.padding.top as f32].into();
|
layout.position() + [self.padding.left as f32, self.padding.top as f32].into();
|
||||||
|
|
@ -266,22 +266,26 @@ where
|
||||||
clip_bounds: Rectangle::new(view_position, Size::new(view_w as f32, view_h as f32)),
|
clip_bounds: Rectangle::new(view_position, Size::new(view_w as f32, view_h as f32)),
|
||||||
});
|
});
|
||||||
|
|
||||||
/*TODO
|
|
||||||
// Draw scrollbar
|
// Draw scrollbar
|
||||||
|
let (start, end) = terminal.scrollbar();
|
||||||
|
let scrollbar_y = start * view_h as f32;
|
||||||
|
let scrollbar_h = end * view_h as f32 - scrollbar_y;
|
||||||
let scrollbar_alpha = match &state.dragging {
|
let scrollbar_alpha = match &state.dragging {
|
||||||
Some(Dragging::Scrollbar { .. }) => 0.5,
|
Some(Dragging::Scrollbar { .. }) => 0.5,
|
||||||
_ => 0.25,
|
_ => 0.25,
|
||||||
};
|
};
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
Quad {
|
Quad {
|
||||||
bounds: state.scrollbar_rect.get() + Vector::new(view_position.x, view_position.y),
|
bounds: Rectangle::new(
|
||||||
|
view_position + Vector::new(view_w as f32, scrollbar_y),
|
||||||
|
Size::new(scrollbar_w, scrollbar_h),
|
||||||
|
),
|
||||||
border_radius: 0.0.into(),
|
border_radius: 0.0.into(),
|
||||||
border_width: 0.0,
|
border_width: 0.0,
|
||||||
border_color: Color::TRANSPARENT,
|
border_color: Color::TRANSPARENT,
|
||||||
},
|
},
|
||||||
Color::new(1.0, 1.0, 1.0, scrollbar_alpha),
|
Color::new(1.0, 1.0, 1.0, scrollbar_alpha),
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
let duration = instant.elapsed();
|
let duration = instant.elapsed();
|
||||||
log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration);
|
log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration);
|
||||||
|
|
@ -349,11 +353,19 @@ where
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
KeyCode::End => {
|
KeyCode::End => {
|
||||||
terminal.input(b"\x1B[F".as_slice());
|
if modifiers.shift() {
|
||||||
|
terminal.scroll(TerminalScroll::Bottom);
|
||||||
|
} else {
|
||||||
|
terminal.input(b"\x1B[F".as_slice());
|
||||||
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
KeyCode::Home => {
|
KeyCode::Home => {
|
||||||
terminal.input(b"\x1B[H".as_slice());
|
if modifiers.shift() {
|
||||||
|
terminal.scroll(TerminalScroll::Top);
|
||||||
|
} else {
|
||||||
|
terminal.input(b"\x1B[H".as_slice());
|
||||||
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
KeyCode::Insert => {
|
KeyCode::Insert => {
|
||||||
|
|
@ -365,11 +377,19 @@ where
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
KeyCode::PageUp => {
|
KeyCode::PageUp => {
|
||||||
terminal.input(b"\x1B[5~".as_slice());
|
if modifiers.shift() {
|
||||||
|
terminal.scroll(TerminalScroll::PageUp);
|
||||||
|
} else {
|
||||||
|
terminal.input(b"\x1B[5~".as_slice());
|
||||||
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
KeyCode::PageDown => {
|
KeyCode::PageDown => {
|
||||||
terminal.input(b"\x1B[6~".as_slice());
|
if modifiers.shift() {
|
||||||
|
terminal.scroll(TerminalScroll::PageDown);
|
||||||
|
} else {
|
||||||
|
terminal.input(b"\x1B[6~".as_slice());
|
||||||
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
//TODO: F1-F12 keys
|
//TODO: F1-F12 keys
|
||||||
|
|
@ -530,6 +550,7 @@ where
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
Event::Mouse(MouseEvent::WheelScrolled { delta }) => {
|
Event::Mouse(MouseEvent::WheelScrolled { delta }) => {
|
||||||
if let Some(_p) = cursor_position.position_in(layout.bounds()) {
|
if let Some(_p) = cursor_position.position_in(layout.bounds()) {
|
||||||
match delta {
|
match delta {
|
||||||
|
|
@ -538,7 +559,7 @@ where
|
||||||
state.scroll_pixels = 0.0;
|
state.scroll_pixels = 0.0;
|
||||||
let lines = (-y * 6.0) as i32;
|
let lines = (-y * 6.0) as i32;
|
||||||
if lines != 0 {
|
if lines != 0 {
|
||||||
editor.action(Action::Scroll { lines });
|
terminal.scroll(TerminalScroll::Delta(-lines));
|
||||||
}
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
|
|
@ -546,7 +567,7 @@ where
|
||||||
//TODO: this adjustment is just a guess!
|
//TODO: this adjustment is just a guess!
|
||||||
state.scroll_pixels -= y * 6.0;
|
state.scroll_pixels -= y * 6.0;
|
||||||
let mut lines = 0;
|
let mut lines = 0;
|
||||||
let metrics = editor.with_buffer(|buffer| buffer.metrics());
|
let metrics = terminal.with_buffer(|buffer| buffer.metrics());
|
||||||
while state.scroll_pixels <= -metrics.line_height {
|
while state.scroll_pixels <= -metrics.line_height {
|
||||||
lines -= 1;
|
lines -= 1;
|
||||||
state.scroll_pixels += metrics.line_height;
|
state.scroll_pixels += metrics.line_height;
|
||||||
|
|
@ -556,14 +577,13 @@ where
|
||||||
state.scroll_pixels -= metrics.line_height;
|
state.scroll_pixels -= metrics.line_height;
|
||||||
}
|
}
|
||||||
if lines != 0 {
|
if lines != 0 {
|
||||||
editor.action(Action::Scroll { lines });
|
terminal.scroll(TerminalScroll::Delta(-lines));
|
||||||
}
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue