mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 15:04:36 +03:00
a lighter way to pass selection ranges for client tabs
This commit is contained in:
parent
b58d329b07
commit
302db2c976
@ -5,6 +5,7 @@ use failure::Error;
|
||||
use portable_pty::{Child, MasterPty, PtySize};
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use term::color::ColorPalette;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{KeyCode, KeyModifiers, MouseEvent, Terminal, TerminalHost};
|
||||
|
||||
pub struct LocalTab {
|
||||
@ -81,6 +82,14 @@ impl Tab for LocalTab {
|
||||
fn domain_id(&self) -> DomainId {
|
||||
self.domain_id
|
||||
}
|
||||
|
||||
fn selection_range(&self) -> Option<SelectionRange> {
|
||||
let terminal = self.terminal.borrow();
|
||||
let rows = terminal.screen().physical_rows;
|
||||
terminal
|
||||
.selection_range()
|
||||
.map(|r| r.clip_to_viewport(terminal.get_viewport_offset(), rows))
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalTab {
|
||||
|
@ -5,6 +5,7 @@ use failure::Fallible;
|
||||
use portable_pty::PtySize;
|
||||
use std::cell::RefMut;
|
||||
use term::color::ColorPalette;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{KeyCode, KeyModifiers, MouseEvent, TerminalHost};
|
||||
|
||||
static TAB_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
|
||||
@ -28,5 +29,10 @@ pub trait Tab: Downcast {
|
||||
fn is_dead(&self) -> bool;
|
||||
fn palette(&self) -> ColorPalette;
|
||||
fn domain_id(&self) -> DomainId;
|
||||
|
||||
/// Returns the selection range adjusted to the viewport
|
||||
/// (eg: it has been normalized and had clip_to_viewport called
|
||||
/// on it prior to being returned)
|
||||
fn selection_range(&self) -> Option<SelectionRange>;
|
||||
}
|
||||
impl_downcast!(Tab);
|
||||
|
@ -19,6 +19,7 @@ use log::debug;
|
||||
use portable_pty::{CommandBuilder, PtySize};
|
||||
use serde_derive::*;
|
||||
use std::sync::Arc;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{CursorPosition, Line};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
use termwiz::surface::{Change, SequenceNo};
|
||||
@ -330,6 +331,7 @@ pub struct SendMouseEvent {
|
||||
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||
pub struct SendMouseEventResponse {
|
||||
pub clipboard: Option<String>,
|
||||
pub selection_range: Option<SelectionRange>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||
|
@ -383,7 +383,7 @@ impl<S: std::io::Read + std::io::Write> ClientSession<S> {
|
||||
Pdu::UnitResponse(UnitResponse {})
|
||||
}
|
||||
Pdu::SendMouseEvent(SendMouseEvent { tab_id, event }) => {
|
||||
let clipboard = Future::with_executor(self.executor.clone_executor(), move || {
|
||||
Future::with_executor(self.executor.clone_executor(), move || {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = mux
|
||||
.get_tab(tab_id)
|
||||
@ -394,10 +394,12 @@ impl<S: std::io::Read + std::io::Write> ClientSession<S> {
|
||||
title: None,
|
||||
};
|
||||
tab.mouse_event(event, &mut host)?;
|
||||
Ok(host.clipboard)
|
||||
Ok(Pdu::SendMouseEventResponse(SendMouseEventResponse {
|
||||
clipboard: host.clipboard,
|
||||
selection_range: tab.selection_range(),
|
||||
}))
|
||||
})
|
||||
.wait()?;
|
||||
Pdu::SendMouseEventResponse(SendMouseEventResponse { clipboard })
|
||||
.wait()?
|
||||
}
|
||||
|
||||
Pdu::Spawn(spawn) => {
|
||||
|
@ -14,6 +14,7 @@ use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use term::color::ColorPalette;
|
||||
use term::selection::SelectionRange;
|
||||
use term::{CursorPosition, Line};
|
||||
use term::{KeyCode, KeyModifiers, MouseEvent, TerminalHost};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
@ -45,6 +46,7 @@ impl ClientTab {
|
||||
surface: RefCell::new(Surface::new(80, 24)),
|
||||
remote_sequence: RefCell::new(0),
|
||||
local_sequence: RefCell::new(0),
|
||||
selection_range: RefCell::new(None),
|
||||
};
|
||||
|
||||
let reader = Pipe::new().expect("Pipe::new failed");
|
||||
@ -130,6 +132,7 @@ impl Tab for ClientTab {
|
||||
if resp.clipboard.is_some() {
|
||||
host.set_clipboard(resp.clipboard)?;
|
||||
}
|
||||
*self.renderable.borrow().selection_range.borrow_mut() = resp.selection_range;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -153,6 +156,10 @@ impl Tab for ClientTab {
|
||||
fn domain_id(&self) -> DomainId {
|
||||
self.client.local_domain_id
|
||||
}
|
||||
|
||||
fn selection_range(&self) -> Option<SelectionRange> {
|
||||
self.renderable.borrow().selection_range.borrow().clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct RenderableState {
|
||||
@ -164,6 +171,7 @@ struct RenderableState {
|
||||
surface: RefCell<Surface>,
|
||||
remote_sequence: RefCell<SequenceNo>,
|
||||
local_sequence: RefCell<SequenceNo>,
|
||||
selection_range: RefCell<Option<SelectionRange>>,
|
||||
}
|
||||
|
||||
const POLL_INTERVAL: Duration = Duration::from_millis(50);
|
||||
@ -228,11 +236,18 @@ impl Renderable for RenderableState {
|
||||
let mut surface = self.surface.borrow_mut();
|
||||
let seq = surface.current_seqno();
|
||||
surface.flush_changes_older_than(seq);
|
||||
let selection = *self.selection_range.borrow();
|
||||
surface
|
||||
.screen_lines()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, line)| (idx, line, 0..0))
|
||||
.map(|(idx, line)| {
|
||||
let r = match selection {
|
||||
None => 0..0,
|
||||
Some(sel) => sel.cols_for_row(idx as i32),
|
||||
};
|
||||
(idx, line, r)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
// The range_plus_one lint can't see when the LHS is not compatible with
|
||||
// and inclusive range
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(clippy::range_plus_one))]
|
||||
use super::ScrollbackOrVisibleRowIndex;
|
||||
use super::{ScrollbackOrVisibleRowIndex, VisibleRowIndex};
|
||||
use serde_derive::*;
|
||||
use std::ops::Range;
|
||||
|
||||
/// The x,y coordinates of either the start or end of a selection region
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SelectionCoordinate {
|
||||
pub x: usize,
|
||||
pub y: ScrollbackOrVisibleRowIndex,
|
||||
@ -13,7 +14,7 @@ pub struct SelectionCoordinate {
|
||||
|
||||
/// Represents the selected text range.
|
||||
/// The end coordinates are inclusive.
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SelectionRange {
|
||||
pub start: SelectionCoordinate,
|
||||
pub end: SelectionCoordinate,
|
||||
@ -26,6 +27,33 @@ impl SelectionRange {
|
||||
Self { start, end }
|
||||
}
|
||||
|
||||
/// Returns a modified version of the selection that is adjusted
|
||||
/// for a Surface that holds only the visible viewport.
|
||||
/// The y values are adjusted such that 0 indicates the top of
|
||||
/// the viewport.
|
||||
pub fn clip_to_viewport(
|
||||
&self,
|
||||
viewport_offset: VisibleRowIndex,
|
||||
height: usize,
|
||||
) -> SelectionRange {
|
||||
let offset = -viewport_offset as ScrollbackOrVisibleRowIndex;
|
||||
let res = SelectionRange {
|
||||
start: SelectionCoordinate {
|
||||
x: self.start.x,
|
||||
y: self.start.y.max(offset) - offset,
|
||||
},
|
||||
end: SelectionCoordinate {
|
||||
x: self.end.x,
|
||||
y: self
|
||||
.end
|
||||
.y
|
||||
.min(offset + height as ScrollbackOrVisibleRowIndex)
|
||||
- offset,
|
||||
},
|
||||
};
|
||||
res
|
||||
}
|
||||
|
||||
/// Returns an extended selection that it ends at the specified location
|
||||
pub fn extend(&self, end: SelectionCoordinate) -> Self {
|
||||
Self {
|
||||
|
@ -590,6 +590,10 @@ impl TerminalState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn selection_range(&self) -> Option<SelectionRange> {
|
||||
self.selection_range.clone().map(|r| r.normalize())
|
||||
}
|
||||
|
||||
fn mouse_drag_left(&mut self, event: MouseEvent) -> Result<(), Error> {
|
||||
// dragging out the selection region
|
||||
// TODO: may drag and change the viewport
|
||||
|
Loading…
Reference in New Issue
Block a user