fix cursor after suspend (#2690)
This was supposed to be fixed by #2569, but I think the actual fix got lost in the refactoring. Intended behavior: pressing ^Z moves the cursor below the viewport before suspending.
This commit is contained in:
@@ -7,6 +7,8 @@ use std::sync::Arc;
|
|||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::sync::atomic::AtomicU8;
|
use std::sync::atomic::AtomicU8;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::sync::atomic::AtomicU16;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -168,6 +170,8 @@ pub struct Tui {
|
|||||||
alt_saved_viewport: Option<ratatui::layout::Rect>,
|
alt_saved_viewport: Option<ratatui::layout::Rect>,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
resume_pending: Arc<AtomicU8>, // Stores a ResumeAction
|
resume_pending: Arc<AtomicU8>, // Stores a ResumeAction
|
||||||
|
#[cfg(unix)]
|
||||||
|
suspend_cursor_y: Arc<AtomicU16>, // Bottom line of inline viewport
|
||||||
// True when overlay alt-screen UI is active
|
// True when overlay alt-screen UI is active
|
||||||
alt_screen_active: Arc<AtomicBool>,
|
alt_screen_active: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
@@ -274,6 +278,8 @@ impl Tui {
|
|||||||
alt_saved_viewport: None,
|
alt_saved_viewport: None,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
resume_pending: Arc::new(AtomicU8::new(0)),
|
resume_pending: Arc::new(AtomicU8::new(0)),
|
||||||
|
#[cfg(unix)]
|
||||||
|
suspend_cursor_y: Arc::new(AtomicU16::new(0)),
|
||||||
alt_screen_active: Arc::new(AtomicBool::new(false)),
|
alt_screen_active: Arc::new(AtomicBool::new(false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,6 +298,8 @@ impl Tui {
|
|||||||
let resume_pending = self.resume_pending.clone();
|
let resume_pending = self.resume_pending.clone();
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let alt_screen_active = self.alt_screen_active.clone();
|
let alt_screen_active = self.alt_screen_active.clone();
|
||||||
|
#[cfg(unix)]
|
||||||
|
let suspend_cursor_y = self.suspend_cursor_y.clone();
|
||||||
let event_stream = async_stream::stream! {
|
let event_stream = async_stream::stream! {
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
@@ -340,6 +348,11 @@ impl Tui {
|
|||||||
} else {
|
} else {
|
||||||
resume_pending.store(ResumeAction::RealignInline as u8, Ordering::Relaxed);
|
resume_pending.store(ResumeAction::RealignInline as u8, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
let y = suspend_cursor_y.load(Ordering::Relaxed);
|
||||||
|
let _ = execute!(stdout(), MoveTo(0, y));
|
||||||
|
}
|
||||||
let _ = execute!(stdout(), crossterm::cursor::Show);
|
let _ = execute!(stdout(), crossterm::cursor::Show);
|
||||||
let _ = Tui::suspend();
|
let _ = Tui::suspend();
|
||||||
yield TuiEvent::Draw;
|
yield TuiEvent::Draw;
|
||||||
@@ -396,7 +409,7 @@ impl Tui {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
ResumeAction::RestoreAlt => {
|
ResumeAction::RestoreAlt => {
|
||||||
if let Ok((_x, y)) = crossterm::cursor::position()
|
if let Ok(ratatui::layout::Position { y, .. }) = self.terminal.get_cursor_position()
|
||||||
&& let Some(saved) = self.alt_saved_viewport.as_mut()
|
&& let Some(saved) = self.alt_saved_viewport.as_mut()
|
||||||
{
|
{
|
||||||
saved.y = y;
|
saved.y = y;
|
||||||
@@ -532,6 +545,19 @@ impl Tui {
|
|||||||
);
|
);
|
||||||
self.pending_history_lines.clear();
|
self.pending_history_lines.clear();
|
||||||
}
|
}
|
||||||
|
// Update the y position for suspending so Ctrl-Z can place the cursor correctly.
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
let inline_area_bottom = if self.alt_screen_active.load(Ordering::Relaxed) {
|
||||||
|
self.alt_saved_viewport
|
||||||
|
.map(|r| r.bottom().saturating_sub(1))
|
||||||
|
.unwrap_or_else(|| area.bottom().saturating_sub(1))
|
||||||
|
} else {
|
||||||
|
area.bottom().saturating_sub(1)
|
||||||
|
};
|
||||||
|
self.suspend_cursor_y
|
||||||
|
.store(inline_area_bottom, Ordering::Relaxed);
|
||||||
|
}
|
||||||
terminal.draw(|frame| {
|
terminal.draw(|frame| {
|
||||||
draw_fn(frame);
|
draw_fn(frame);
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
Reference in New Issue
Block a user