aboutsummaryrefslogtreecommitdiff
path: root/src/client/shell/workspace_navigation.rs
diff options
context:
space:
mode:
authorEric Yue <jiacheng.yue@foxmail.com>2026-09-20 22:33:50 +0800
committerGitHub <noreply@github.com>2026-09-20 16:33:50 +0200
commit74505861e40c48e070e711bd4de662a17b0939b3 (patch)
tree736ad65c9dba956554529b4169bc54827dc342e3 /src/client/shell/workspace_navigation.rs
parentc00a62dda169beb472fc2f386d0f673ca100dfa4 (diff)
fix: keep workspace navigation visible in terminal theme (#4408)
* fix: keep workspace navigation visible in terminal theme refs #4300 * fix: clear workspace highlight on directional pane focus refs #4300 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/client/shell/workspace_navigation.rs')
-rw-r--r--src/client/shell/workspace_navigation.rs54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/client/shell/workspace_navigation.rs b/src/client/shell/workspace_navigation.rs
index 6139fe0d..19fa1a39 100644
--- a/src/client/shell/workspace_navigation.rs
+++ b/src/client/shell/workspace_navigation.rs
@@ -9,6 +9,13 @@ pub(super) struct WorkspaceNavigationTarget {
generation: Option<u64>,
}
+/// Display-only continuity while a direct focus request awaits its authoritative snapshot.
+pub(super) struct PendingWorkspaceHighlight {
+ pub(super) target: WorkspaceNavigationTarget,
+ pub(super) request_id: String,
+ expires_at: std::time::Instant,
+}
+
impl WorkspaceNavigationTarget {
pub(super) fn matches(&self, endpoint_id: &ClientEndpointId, workspace_id: &str) -> bool {
&self.endpoint_id == endpoint_id && self.workspace_id == workspace_id
@@ -16,6 +23,35 @@ impl WorkspaceNavigationTarget {
}
impl ClientShellState {
+ pub(crate) fn tick_workspace_highlight(&mut self, now: std::time::Instant) -> bool {
+ if self
+ .pending_workspace_highlight
+ .as_ref()
+ .is_some_and(|pending| now >= pending.expires_at)
+ {
+ self.pending_workspace_highlight = None;
+ return true;
+ }
+ false
+ }
+
+ pub(super) fn reconcile_pending_workspace_highlight(&mut self) {
+ if self
+ .pending_workspace_highlight
+ .as_ref()
+ .is_some_and(|pending| {
+ pending.target.endpoint_id != self.active_endpoint_id
+ || !self.navigation_target_valid(&pending.target)
+ || self.snapshot.as_deref().is_some_and(|snapshot| {
+ snapshot.focused_workspace_id.as_deref()
+ == Some(pending.target.workspace_id.as_str())
+ })
+ })
+ {
+ self.pending_workspace_highlight = None;
+ }
+ }
+
pub(super) fn navigation_target(
&self,
endpoint_id: &ClientEndpointId,
@@ -140,11 +176,25 @@ impl ClientShellState {
outcome.repaint = true;
return;
}
+ let action_index = outcome.actions.len();
if self.focus_or_activate(
- target.endpoint_id,
- ClientEndpointFocusTarget::Workspace(target.workspace_id),
+ target.endpoint_id.clone(),
+ ClientEndpointFocusTarget::Workspace(target.workspace_id.clone()),
outcome,
) {
+ // Endpoint handoffs already retain their coherent source frame in the runtime.
+ // Only retain a highlight if a focus request was actually enqueued.
+ if let Some(ClientShellAction::Endpoint { request, .. }) =
+ outcome.actions.get(action_index)
+ {
+ self.pending_workspace_highlight = Some(PendingWorkspaceHighlight {
+ target,
+ request_id: request.id.clone(),
+ // A later focus can be coalesced with this one before a snapshot is sent.
+ expires_at: std::time::Instant::now() + std::time::Duration::from_secs(1),
+ });
+ self.reconcile_pending_workspace_highlight();
+ }
self.mode = ClientShellMode::Terminal;
self.navigate_workspace_id = None;
}