Skip to content

fix: reset widget state when terminal ID changes (multi-terminal resize)#70

Merged
Harzu merged 2 commits intoHarzu:masterfrom
vjvaldi:fix/multi-terminal-resize
Apr 3, 2026
Merged

fix: reset widget state when terminal ID changes (multi-terminal resize)#70
Harzu merged 2 commits intoHarzu:masterfrom
vjvaldi:fix/multi-terminal-resize

Conversation

@felixn678
Copy link
Copy Markdown
Contributor

Summary

Fixes #67 — when using multiple terminal instances with tab switching or pane_grid, non-first terminals render with wrong column count (~10 instead of 80+).

Root Cause

TerminalViewState.size persists across different terminals due to Iced's Tree reconciliation (diff()). When switching from Terminal A to Terminal B in the same widget position, the state from A (with size already set to the correct layout dimensions) is reused for B. The resize check state.size != layout_size evaluates to false, so Command::Resize is never published for the new terminal.

Changes

Only src/view.rs — 9 lines added, 0 removed:

  1. Added terminal_id: Option<u64> field to TerminalViewState
  2. In handle_resize(), detect when the state is recycled for a different terminal and reset size to (0, 0) to force the resize check to fire

How to Reproduce

  1. Create an app using pane_grid with multiple Terminal instances (tab switching)
  2. Terminal #0 renders correctly (80+ columns)
  3. Switch to Terminal make widget from POC #1 → only ~10 columns, garbled display

After this fix, all terminals resize correctly when switching.

Test Plan

  • Multi-tab app: all terminals resize correctly on tab switch
  • Split panes: new panes get correct dimensions
  • First terminal unchanged behavior
  • cargo check passes

When Iced's Tree reconciliation recycles TerminalViewState for a
different terminal (e.g., tab switching in a multi-tab app), the
cached layout size prevents the resize check from firing.
The new terminal's PTY stays at ~10 columns instead of resizing
to match the actual widget dimensions.

Fix: track terminal_id in TerminalViewState. When the state is
reused for a different terminal, reset size to zero to force resize.

Closes Harzu#67
@felixn678
Copy link
Copy Markdown
Contributor Author

felixn678 commented Mar 31, 2026

Reproduction Video

Before fix (iced_term 0.8.0 from crates.io)

Tab 1 works, Tab 2+ has wrong column count (~10 instead of 80:

Screen.Recording.2026-03-31.at.15.12.27.mov

After fix (this PR)

All tabs resize correctly:

Screen.Recording.2026-03-31.at.15.14.51.mov

@Harzu here are the reproduction videos showing the bug and the fix.

Comment thread src/view.rs Outdated
Comment thread src/view.rs Outdated
Address PR review feedback from @Harzu:
- Move terminal ID check from handle_resize() to Widget::diff()
- Change terminal_id from Option<u64> to u64
- Initialize terminal_id in state() via TerminalViewState::new(id)
- Remove Default impl for TerminalViewState

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@felixn678
Copy link
Copy Markdown
Contributor Author

@Harzu Thanks for the review! I've addressed all your feedback in d9b343f:

  1. Replaced Option<u64> with u64terminal_id is now initialized directly in state() via TerminalViewState::new(self.term.id)
  2. Removed the Default impl for TerminalViewState
  3. Moved the terminal ID check from handle_resize() to Widget::diff() — much more idiomatic

Ready for another look when you get a chance!

@felixn678 felixn678 requested a review from Harzu April 3, 2026 11:06
@Harzu Harzu merged commit f2d8232 into Harzu:master Apr 3, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multi-terminal bug: widget state recycling causes wrong column count on tab switch

2 participants