fix: selection range desync and arrow pointer in alternate screen
This commit is contained in:
+39
-17
@@ -2115,8 +2115,7 @@ impl App {
|
|||||||
for (pane_id, _) in &geometries {
|
for (pane_id, _) in &geometries {
|
||||||
if let Some(pane) = tab.panes.get_mut(pane_id) {
|
if let Some(pane) = tab.panes.get_mut(pane_id) {
|
||||||
if pane.terminal.using_alternate_screen {
|
if pane.terminal.using_alternate_screen {
|
||||||
pane.selection = None;
|
// Keep selection if it's being modified by the user
|
||||||
pane.is_selecting = false;
|
|
||||||
}
|
}
|
||||||
let is_active = *pane_id == active_pane_id;
|
let is_active = *pane_id == active_pane_id;
|
||||||
let dim_factor = pane.calculate_dim_factor(
|
let dim_factor = pane.calculate_dim_factor(
|
||||||
@@ -3230,19 +3229,35 @@ impl ApplicationHandler<UserEvent> for App {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set cursor icon to IBeam when hovering over a pane
|
// Set cursor icon to IBeam when hovering over a pane, unless it's an alternate screen
|
||||||
if let Some(window) = &self.window {
|
if let Some(window) = &self.window {
|
||||||
let icon = if pane_geom.is_some() {
|
let icon = if let Some(geom) = &pane_geom {
|
||||||
CursorIcon::Text
|
let is_alt = if let Some(tab) = self.active_tab() {
|
||||||
} else {
|
tab.panes
|
||||||
CursorIcon::Default
|
.get(&geom.pane_id)
|
||||||
};
|
.map(|p| p.terminal.using_alternate_screen)
|
||||||
window.set_cursor(icon);
|
.unwrap_or(false)
|
||||||
}
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if is_alt {
|
||||||
|
CursorIcon::Default
|
||||||
|
} else {
|
||||||
|
CursorIcon::Text
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CursorIcon::Default
|
||||||
|
};
|
||||||
|
window.set_cursor(icon);
|
||||||
|
}
|
||||||
|
|
||||||
// Switch focus if dragging on a different pane
|
// Switch focus if dragging on a different pane
|
||||||
if self.mouse_down_pos.is_some() {
|
if self.mouse_down_pos.is_some() {
|
||||||
if let Some(geom) = &pane_geom {
|
if let Some(renderer) = &mut self.renderer {
|
||||||
|
renderer.force_full_redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(geom) = &pane_geom {
|
||||||
if let Some(tab) = self.active_tab_mut() {
|
if let Some(tab) = self.active_tab_mut() {
|
||||||
if tab.active_pane != geom.pane_id {
|
if tab.active_pane != geom.pane_id {
|
||||||
if tab.focus_pane_by_id(geom.pane_id) {
|
if tab.focus_pane_by_id(geom.pane_id) {
|
||||||
@@ -3263,8 +3278,9 @@ impl ApplicationHandler<UserEvent> for App {
|
|||||||
})
|
})
|
||||||
.map(|p| p.is_selecting)
|
.map(|p| p.is_selecting)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let is_selecting =
|
let is_selecting =
|
||||||
active_is_selecting || mouse_pane_is_selecting;
|
(active_is_selecting || mouse_pane_is_selecting)
|
||||||
|
|| self.mouse_down_pos.is_some();
|
||||||
|
|
||||||
let mouse_tracking = pane_geom
|
let mouse_tracking = pane_geom
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -3521,6 +3537,14 @@ impl ApplicationHandler<UserEvent> for App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WindowEvent::MouseInput { state, button, .. } => {
|
WindowEvent::MouseInput { state, button, .. } => {
|
||||||
|
if button == MouseButton::Left {
|
||||||
|
self.mouse_down_pos = if state == ElementState::Pressed {
|
||||||
|
Some(self.cursor_position)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let button_code = match button {
|
let button_code = match button {
|
||||||
MouseButton::Left => 0,
|
MouseButton::Left => 0,
|
||||||
MouseButton::Middle => 1,
|
MouseButton::Middle => 1,
|
||||||
@@ -3612,7 +3636,6 @@ impl ApplicationHandler<UserEvent> for App {
|
|||||||
} else if button == MouseButton::Left {
|
} else if button == MouseButton::Left {
|
||||||
match state {
|
match state {
|
||||||
ElementState::Pressed => {
|
ElementState::Pressed => {
|
||||||
self.mouse_down_pos = Some(self.cursor_position);
|
|
||||||
if let Some(tab) = self.active_tab_mut() {
|
if let Some(tab) = self.active_tab_mut() {
|
||||||
if let Some(pane) = tab.active_pane_mut() {
|
if let Some(pane) = tab.active_pane_mut() {
|
||||||
pane.selection = None;
|
pane.selection = None;
|
||||||
@@ -3624,7 +3647,6 @@ impl ApplicationHandler<UserEvent> for App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElementState::Released => {
|
ElementState::Released => {
|
||||||
self.mouse_down_pos = None;
|
|
||||||
let was_selecting = self
|
let was_selecting = self
|
||||||
.active_pane()
|
.active_pane()
|
||||||
.map(|p| p.is_selecting)
|
.map(|p| p.is_selecting)
|
||||||
|
|||||||
+15
-2
@@ -20,7 +20,7 @@ use crate::graphics::ImageStorage;
|
|||||||
use crate::image_renderer::ImageRenderer;
|
use crate::image_renderer::ImageRenderer;
|
||||||
use crate::pane_resources::PaneGpuResources;
|
use crate::pane_resources::PaneGpuResources;
|
||||||
use crate::pipeline::PipelineBuilder;
|
use crate::pipeline::PipelineBuilder;
|
||||||
use crate::terminal::{Color, ColorPalette, CursorShape, Direction, Terminal};
|
use crate::terminal::{Cell, Color, ColorPalette, CursorShape, Direction, Terminal};
|
||||||
use ab_glyph::{Font, FontRef, GlyphId, ScaleFont};
|
use ab_glyph::{Font, FontRef, GlyphId, ScaleFont};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustybuzz::UnicodeBuffer;
|
use rustybuzz::UnicodeBuffer;
|
||||||
@@ -5541,7 +5541,20 @@ impl Renderer {
|
|||||||
for row in *sr..=*er {
|
for row in *sr..=*er {
|
||||||
if row < 256 && row < rows as usize {
|
if row < 256 && row < rows as usize {
|
||||||
let mut max_col = -1i32;
|
let mut max_col = -1i32;
|
||||||
let row_cells = &terminal.grid[row as usize];
|
let row_cells: &[Cell] = if row < terminal.scroll_offset {
|
||||||
|
terminal.scrollback.get(
|
||||||
|
terminal.scrollback.len()
|
||||||
|
.saturating_sub(terminal.scroll_offset)
|
||||||
|
+ row as usize,
|
||||||
|
).map(|c| c.as_slice()).unwrap_or(&[])
|
||||||
|
} else {
|
||||||
|
let grid_row = (row as usize).saturating_sub(terminal.scroll_offset);
|
||||||
|
if grid_row < terminal.line_map.len() {
|
||||||
|
&terminal.grid[terminal.line_map[grid_row]]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
};
|
||||||
for col in 0..row_cells.len() {
|
for col in 0..row_cells.len() {
|
||||||
let cell = &row_cells[col];
|
let cell = &row_cells[col];
|
||||||
if cell.character != ' ' || cell.wide_continuation {
|
if cell.character != ' ' || cell.wide_continuation {
|
||||||
|
|||||||
+1
-1
@@ -418,7 +418,7 @@ pub struct Terminal {
|
|||||||
pub grid: Vec<Vec<Cell>>,
|
pub grid: Vec<Vec<Cell>>,
|
||||||
/// Maps visual row index to actual grid row index.
|
/// Maps visual row index to actual grid row index.
|
||||||
/// This allows O(1) scrolling by rotating indices instead of moving cells.
|
/// This allows O(1) scrolling by rotating indices instead of moving cells.
|
||||||
line_map: Vec<usize>,
|
pub line_map: Vec<usize>,
|
||||||
/// Number of columns.
|
/// Number of columns.
|
||||||
pub cols: usize,
|
pub cols: usize,
|
||||||
/// Number of rows.
|
/// Number of rows.
|
||||||
|
|||||||
Reference in New Issue
Block a user