aboutsummaryrefslogtreecommitdiff
path: root/src/server/client_shell.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/client_shell.rs')
-rw-r--r--src/server/client_shell.rs143
1 files changed, 94 insertions, 49 deletions
diff --git a/src/server/client_shell.rs b/src/server/client_shell.rs
index 8f0a90ee..f511b641 100644
--- a/src/server/client_shell.rs
+++ b/src/server/client_shell.rs
@@ -8,8 +8,30 @@ pub(super) fn snapshot(
boot_id: &str,
revision: u64,
config_diagnostic: Option<&str>,
+ location: Option<&crate::server::clients::ClientShellLocation>,
) -> protocol::ClientShellSnapshot {
let snapshot = app.session_snapshot();
+ let focused_workspace_id = location
+ .and_then(|location| location.focused_workspace_id.clone())
+ .or_else(|| snapshot.focused_workspace_id.clone());
+ let focused_tab_id = location
+ .and_then(|location| location.focused_tab_id().map(str::to_owned))
+ .or_else(|| snapshot.focused_tab_id.clone());
+ let focused_pane_id = focused_tab_id
+ .as_deref()
+ .and_then(|tab_id| app.parse_tab_id(tab_id))
+ .and_then(|(workspace_index, tab_index)| {
+ let pane_id = app
+ .state
+ .workspaces
+ .get(workspace_index)?
+ .tabs
+ .get(tab_index)?
+ .layout
+ .focused();
+ app.public_pane_id(workspace_index, pane_id)
+ })
+ .or_else(|| snapshot.focused_pane_id.clone());
let workspaces = snapshot
.workspaces
.into_iter()
@@ -18,11 +40,22 @@ pub(super) fn snapshot(
.map(|(workspace_index, (workspace, state))| {
let mut tokens = workspace.tokens.into_iter().collect::<Vec<_>>();
tokens.sort_by(|left, right| left.0.cmp(&right.0));
+ let workspace_id = workspace.workspace_id;
+ let active_tab_id = location
+ .and_then(|location| location.active_tab_ids.get(&workspace_id))
+ .cloned()
+ .unwrap_or(workspace.active_tab_id);
+ let active_tab_index =
+ app.parse_tab_id(&active_tab_id)
+ .and_then(|(tab_workspace_index, tab_index)| {
+ (tab_workspace_index == workspace_index).then_some(tab_index)
+ });
protocol::ClientShellWorkspace {
- workspace_id: workspace.workspace_id,
- active_tab_id: workspace.active_tab_id,
+ focused: focused_workspace_id.as_deref() == Some(workspace_id.as_str()),
+ workspace_id,
+ active_tab_id,
new_workspace_cwd: app
- .resolved_new_workspace_cwd_from(workspace_index)
+ .resolved_new_workspace_cwd_from_tab(workspace_index, active_tab_index)
.display()
.to_string(),
number: workspace.number,
@@ -38,7 +71,6 @@ pub(super) fn snapshot(
label: worktree.repo_name,
is_linked_worktree: worktree.is_linked_worktree,
}),
- focused: workspace.focused,
agent_status: workspace.agent_status,
}
})
@@ -52,23 +84,28 @@ pub(super) fn snapshot(
.iter()
.flat_map(|workspace| workspace.tabs.iter()),
)
- .map(|(tab, state)| protocol::ClientShellTab {
- tab_id: tab.tab_id,
- workspace_id: tab.workspace_id,
- number: tab.number,
- label: tab.label,
- custom_label: !state.is_auto_named(),
- zoomed: state.zoomed,
- focused: tab.focused,
- agent_status: tab.agent_status,
+ .map(|(tab, state)| {
+ let tab_id = tab.tab_id;
+ protocol::ClientShellTab {
+ focused: focused_tab_id.as_deref() == Some(tab_id.as_str()),
+ tab_id,
+ workspace_id: tab.workspace_id,
+ number: tab.number,
+ label: tab.label,
+ custom_label: !state.is_auto_named(),
+ zoomed: state.zoomed,
+ agent_status: tab.agent_status,
+ }
})
.collect();
let panes = snapshot
.panes
.into_iter()
.map(|pane| {
+ let pane_id = pane.pane_id;
+ let focused = focused_pane_id.as_deref() == Some(pane_id.as_str());
let right_click_passthrough = app
- .parse_pane_id(&pane.pane_id)
+ .parse_pane_id(&pane_id)
.and_then(|(workspace_index, pane_id)| {
app.state
.workspaces
@@ -77,13 +114,13 @@ pub(super) fn snapshot(
})
.is_some_and(|pane| pane.right_click_passthrough);
protocol::ClientShellPane {
- pane_id: pane.pane_id,
+ pane_id,
workspace_id: pane.workspace_id,
tab_id: pane.tab_id,
label: pane.label,
cwd: pane.cwd,
foreground_cwd: pane.foreground_cwd,
- focused: pane.focused,
+ focused,
right_click_passthrough,
}
})
@@ -92,12 +129,14 @@ pub(super) fn snapshot(
.agents
.into_iter()
.map(|agent| {
+ let pane_id = agent.pane_id;
+ let focused = focused_pane_id.as_deref() == Some(pane_id.as_str());
let mut state_labels = agent.state_labels.into_iter().collect::<Vec<_>>();
state_labels.sort_by(|left, right| left.0.cmp(&right.0));
let mut tokens = agent.tokens.into_iter().collect::<Vec<_>>();
tokens.sort_by(|left, right| left.0.cmp(&right.0));
protocol::ClientShellAgent {
- pane_id: agent.pane_id,
+ pane_id,
workspace_id: agent.workspace_id,
tab_id: agent.tab_id,
name: agent.name,
@@ -110,7 +149,7 @@ pub(super) fn snapshot(
state_change_seq: agent.state_change_seq,
state_labels,
tokens,
- focused: agent.focused,
+ focused,
}
})
.collect();
@@ -125,11 +164,17 @@ pub(super) fn snapshot(
.filter_map(|entry| app.public_pane_id(entry.ws_idx, entry.pane_id))
.collect();
- let zoomed = app
- .state
- .active
- .and_then(|index| app.state.workspaces.get(index))
- .is_some_and(|workspace| workspace.zoomed);
+ let zoomed = focused_tab_id
+ .as_deref()
+ .and_then(|tab_id| app.parse_tab_id(tab_id))
+ .and_then(|(workspace_index, tab_index)| {
+ app.state
+ .workspaces
+ .get(workspace_index)?
+ .tabs
+ .get(tab_index)
+ })
+ .is_some_and(|tab| tab.zoomed);
let tab_bar_right = app
.state
.tab_bar_right
@@ -183,9 +228,9 @@ pub(super) fn snapshot(
integration_updates_available: app.state.integration_updates_available(),
worktree_directory: app.state.worktree_directory.to_string_lossy().into_owned(),
release_notes,
- focused_workspace_id: snapshot.focused_workspace_id,
- focused_tab_id: snapshot.focused_tab_id,
- focused_pane_id: snapshot.focused_pane_id,
+ focused_workspace_id,
+ focused_tab_id,
+ focused_pane_id,
tab_bar_right,
tab_bar_right_separator: app.state.tab_bar_right_separator.clone(),
agent_view_label,
@@ -209,18 +254,18 @@ pub(super) struct RenderedPaneSurface {
pub(super) fn render_pane_surface(
app: &mut app::App,
+ target: Option<crate::ui::TabSurfaceTarget>,
area: Rect,
- is_foreground: bool,
+ resize_panes: bool,
+ show_popup: bool,
cell_size: crate::kitty_graphics::HostCellSize,
graphics_delivery: &crate::kitty_graphics::surface::DeliveryCache,
client_id: u64,
) -> RenderedPaneSurface {
- let content_revisions_before = app
- .state
- .active
- .and_then(|workspace_index| {
- let workspace = app.state.workspaces.get(workspace_index)?;
- let tab = workspace.tabs.get(workspace.active_tab)?;
+ let content_revisions_before = target
+ .and_then(|target| {
+ let workspace = app.state.workspaces.get(target.workspace_index)?;
+ let tab = workspace.tabs.get(target.tab_index)?;
Some(
tab.layout
.pane_ids()
@@ -229,7 +274,7 @@ pub(super) fn render_pane_surface(
app.state
.runtime_for_pane_in_workspace(
&app.terminal_runtimes,
- workspace_index,
+ target.workspace_index,
pane_id,
)
.map(|runtime| (pane_id, runtime.content_seq()))
@@ -242,14 +287,14 @@ pub(super) fn render_pane_surface(
crate::server::render_stream::render_tab_surface_virtual(
&app.state,
&app.terminal_runtimes,
+ target,
area,
- is_foreground,
+ resize_panes,
cell_size,
);
- let panes = app
- .state
- .active
- .map(|workspace_index| {
+ let panes = target
+ .map(|target| {
+ let workspace_index = target.workspace_index;
layout
.pane_infos
.iter()
@@ -340,12 +385,15 @@ pub(super) fn render_pane_surface(
})
})
.collect();
- let popup = render_popup_surface(app, area, is_foreground, cell_size);
+ let popup = show_popup
+ .then(|| render_popup_surface(app, area, resize_panes, cell_size))
+ .flatten();
let (graphics, next_graphics_delivery) = crate::server::client_shell_graphics::collect(
app,
&layout.pane_infos,
&layout.split_borders,
popup.as_deref(),
+ target,
cell_size,
graphics_delivery,
client_id,
@@ -363,22 +411,19 @@ pub(super) fn render_pane_surface(
fn render_popup_surface(
app: &app::App,
area: Rect,
- is_foreground: bool,
+ resize_runtime: bool,
cell_size: crate::kitty_graphics::HostCellSize,
) -> Option<Box<protocol::ClientShellPopupSurface>> {
let popup = app.state.popup_pane.as_ref()?;
- let geometry = if is_foreground {
+ let geometry = if resize_runtime {
resize_popup_runtime(app, area, cell_size)?
} else {
crate::popup_size::resolve_popup_geometry(popup.width, popup.height, area)?
};
let runtime = app.terminal_runtimes.get(&popup.terminal_id)?;
let content_area = Rect::new(0, 0, geometry.inner.width, geometry.inner.height);
- let (buffer, mut cursor) =
+ let (buffer, cursor) =
crate::server::render_stream::render_terminal_virtual(runtime, content_area);
- if !is_foreground {
- cursor = None;
- }
let hyperlinks = runtime.visible_hyperlinks(content_area);
let title = app
.state
@@ -518,7 +563,7 @@ mod tests {
preview: true,
});
- let snapshot = snapshot(&app, "boot", 7, None);
+ let snapshot = snapshot(&app, "boot", 7, None, None);
assert_eq!(snapshot.update_available.as_deref(), Some("0.8.3"));
assert_eq!(snapshot.update_install_command, "herdr update");
@@ -554,11 +599,11 @@ mod tests {
state: crate::integration::IntegrationStatusKind::NotInstalled,
}];
- assert!(!snapshot(&app, "boot", 1, None).integration_updates_available);
+ assert!(!snapshot(&app, "boot", 1, None, None).integration_updates_available);
app.state.integration_recommendations[0].state =
crate::integration::IntegrationStatusKind::Outdated;
- assert!(snapshot(&app, "boot", 2, None).integration_updates_available);
+ assert!(snapshot(&app, "boot", 2, None, None).integration_updates_available);
}
#[test]