aboutsummaryrefslogtreecommitdiff
path: root/src/selection.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-01 15:48:22 +0300
committerGitHub <noreply@github.com>2026-09-01 15:48:22 +0300
commit207be3c771d281baae6e5fa0fb74be9a056e97a2 (patch)
treed7b037ecdf629224a048c841d11659efdc23507d /src/selection.rs
parent8a6d697308162874a236c84aac0b0f8c7ac01f83 (diff)
refactor: render the shell in the client (#3487)
* feat: add opt-in client-rendered shell * feat: add client-owned shell mouse controls * feat: complete client-owned shell chrome * feat: add client-owned shell settings and notifications * feat: run client shell custom commands * feat: render popup terminals in client shell * feat: add client-owned scrollback and copy mode * fix: preserve client worktree trust defaults * feat: render startup diagnostics in client shell * feat: render onboarding in client shell * feat: render product announcements in client shell * feat: render release notes in client shell * feat: render mobile switcher in client shell * feat: render kitty graphics in client shell * fix: preserve client shell lifecycle coherence * refactor: route client shell commands through endpoint connections * refactor: make the client-rendered shell the default * refactor: remove monolithic launch mode * refactor: complete client-rendered shell cutover * perf: retain client pane surface updates * perf: scale retained pane surface updates * perf: remove remote pane input latency * test: make client shell checks platform-independent * fix: prevent client timer starvation * test: fix client shell platform gates * test: accept retained surfaces in cross-area checks * test: make client mode assertions platform-neutral * fix: badge only outdated integrations
Diffstat (limited to 'src/selection.rs')
-rw-r--r--src/selection.rs64
1 files changed, 24 insertions, 40 deletions
diff --git a/src/selection.rs b/src/selection.rs
index 08af95f5..7290b8f0 100644
--- a/src/selection.rs
+++ b/src/selection.rs
@@ -32,9 +32,9 @@ enum Phase {
/// A text selection within a terminal pane.
#[derive(Debug, Clone)]
-pub struct Selection {
+pub struct Selection<P = PaneId> {
/// Which pane the selection belongs to.
- pub pane_id: PaneId,
+ pub pane_id: P,
/// Anchor position in screen-buffer coordinates (row, col).
anchor: (u32, u16),
/// Current/final position in screen-buffer coordinates (row, col).
@@ -43,15 +43,10 @@ pub struct Selection {
phase: Phase,
}
-impl Selection {
+impl<P> Selection<P> {
/// Start a potential selection. This records the anchor but doesn't
/// make anything visible yet — the user might just be clicking.
- pub fn anchor(
- pane_id: PaneId,
- viewport_row: u16,
- col: u16,
- metrics: Option<ScrollMetrics>,
- ) -> Self {
+ pub fn anchor(pane_id: P, viewport_row: u16, col: u16, metrics: Option<ScrollMetrics>) -> Self {
let anchor = (absolute_row_for_viewport_row(viewport_row, metrics), col);
Self {
pane_id,
@@ -61,29 +56,25 @@ impl Selection {
}
}
- /// Create an active selection from an explicit viewport-row range.
- pub(crate) fn range(
- pane_id: PaneId,
- viewport_row: u16,
- start_col: u16,
- end_col: u16,
- metrics: Option<ScrollMetrics>,
- ) -> Self {
- let row = absolute_row_for_viewport_row(viewport_row, metrics);
+ pub(crate) fn absolute_anchor(pane_id: P, anchor: (u32, u16)) -> Self {
+ Self {
+ pane_id,
+ anchor,
+ cursor: anchor,
+ phase: Phase::Anchored,
+ }
+ }
+
+ pub(crate) fn absolute_range(pane_id: P, anchor: (u32, u16), cursor: (u32, u16)) -> Self {
Self {
pane_id,
- anchor: (row, start_col),
- cursor: (row, end_col),
+ anchor,
+ cursor,
phase: Phase::Dragging,
}
}
- pub(crate) fn line_range(
- pane_id: PaneId,
- anchor_row: u32,
- cursor_row: u32,
- end_col: u16,
- ) -> Self {
+ pub(crate) fn line_range(pane_id: P, anchor_row: u32, cursor_row: u32, end_col: u16) -> Self {
let (anchor_col, cursor_col) = if anchor_row <= cursor_row {
(0, end_col)
} else {
@@ -97,13 +88,6 @@ impl Selection {
}
}
- pub(crate) fn absolute_row_for_viewport(
- viewport_row: u16,
- metrics: Option<ScrollMetrics>,
- ) -> u32 {
- absolute_row_for_viewport_row(viewport_row, metrics)
- }
-
/// Convert the anchor's absolute row and pane-relative column back to
/// screen coordinates. Adds the pane origin before clamping so the
/// returned (screen_row, screen_col) can be compared directly against
@@ -160,16 +144,12 @@ impl Selection {
}
/// Whether this selection was already finalized.
+ #[cfg(test)]
pub fn is_finalized(&self) -> bool {
self.phase == Phase::Done
}
/// Whether the user just clicked without dragging (not a selection).
- pub fn was_just_click(&self) -> bool {
- self.phase == Phase::Anchored
- }
-
- /// Whether the user just clicked without dragging (not a selection).
pub fn is_just_click(&self) -> bool {
self.phase == Phase::Anchored
}
@@ -240,6 +220,10 @@ fn viewport_top_row(metrics: Option<ScrollMetrics>) -> u32 {
.unwrap_or(0) as u32
}
+pub(crate) fn absolute_row_for_viewport(viewport_row: u16, metrics: Option<ScrollMetrics>) -> u32 {
+ absolute_row_for_viewport_row(viewport_row, metrics)
+}
+
fn absolute_row_for_viewport_row(viewport_row: u16, metrics: Option<ScrollMetrics>) -> u32 {
viewport_top_row(metrics) + u32::from(viewport_row)
}
@@ -485,7 +469,7 @@ mod tests {
#[test]
fn click_without_drag() {
let mut sel = Selection::anchor(PaneId::from_raw(0), 5, 10, None);
- assert!(sel.was_just_click());
+ assert!(sel.is_just_click());
let copied = sel.finish();
assert!(!copied);
}
@@ -495,7 +479,7 @@ mod tests {
let mut sel = Selection::anchor(PaneId::from_raw(0), 5, 10, None);
sel.drag(20, 7, Rect::new(10, 5, 80, 24), None);
assert!(sel.is_visible());
- assert!(!sel.was_just_click());
+ assert!(!sel.is_just_click());
let copied = sel.finish();
assert!(copied);
}