Repository navigation
Terminal: fix moving a terminal tab to another terminals view - #2979
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Test teardown leaks terminal resources, and both modified plug-ins require bundle version increments.
Review effort: Balanced
Findings: 1
Open (3)
What changed in this PR
Fixes terminal tab migration between terminal views by safely recreating controls and preserving preferences.
Changes:
- Avoids measuring fonts against a disposed canvas.
- Reapplies terminal preferences after control recreation.
- Adds UI regression coverage for recreation and preference retention.
| File | Description |
|---|---|
AutomatedTestSuite.java |
Registers the new UI test. |
TerminalControlRecreateUITest.java |
Tests control recreation and preference retention. |
VT100TerminalControl.java |
Fixes recreation and reapplies preferences. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This pull request changes some projects for the first time in this development cycle. An additional commit containing all the necessary changes was pushed to the top of this PR's branch. To obtain these changes (for example if you want to push more changes) either fetch from your fork or apply the git patch. Git patchFurther information are available in Common Build Issues - Missing version increments. |
akurtakov
left a comment
There was a problem hiding this comment.
Thanks, this fixes the drag and drop: I reproduced Widget is disposed on master and the move works with this PR. One gap: inverted colors set on a terminal are reset to the preference when it is moved (details inline). Please also rebase on master and squash into one commit; the version bump commit is no longer needed, master is at 1.1.300 already.
| setupListeners(); | ||
| if (fPreferenceStore != null && wasDisposed) { | ||
| if (fPreferenceStore != null) { | ||
| // new controls after a drag and drop need the colors and font as well |
There was a problem hiding this comment.
Inverted colors set on one terminal (right-click → Inverted colors, InvertColorsAction) are lost when the tab is moved: updatePreferences() resets them to PREF_INVERT_COLORS. To reproduce, invert a terminal with the global preference off, drag it to another Terminals view, and it arrives not inverted. The flag lives on the canvas (fCtlText.isInvertedColors()), so reading it before fWndParent.dispose() and setting it on the new canvas after updatePreferences() would keep it.
A smaller point on the same line: re-running updatePreferences() on a move also calls setBufferLineLimit(pref), which trims history if a client set a different limit through ITerminalViewControl. The Terminals view never does, so this is only for other users of the control; skipping the buffer limit on a move would avoid it.
There was a problem hiding this comment.
Fixed in c069116. On a move, setupTerminal() no longer runs updatePreferences(): it reads the inverted colors from the old canvas before disposing its parent, applies only the colors and the font from the preferences to the new canvas, and sets the inverted colors back. The buffer line limit is left as it was, so a limit set through ITerminalViewControl survives the move too.
| new TextLineRenderer(() -> fCtlText, fPollingTextCanvasModel)); | ||
| // While the canvas is being created, fCtlText may still be the canvas disposed by a | ||
| // drag and drop to another tab folder: measure on the display then | ||
| new TextLineRenderer(() -> fCtlText != null && !fCtlText.isDisposed() ? fCtlText : null, |
There was a problem hiding this comment.
Optional: rather than checking isDisposed() on every font measurement, setupTerminal() could set fCtlText = null once it disposes the old parent, and the supplier could stay () -> fCtlText. That keeps the invariant in one place and drops the need for the comment.
There was a problem hiding this comment.
Done: setupTerminal() sets fCtlText to null once the old parent is disposed, and the renderer gets () -> fCtlText. StyleMap already measures on the display when the supplier gives null, so the comment is gone.
| } | ||
|
|
||
| @Test | ||
| public void recreatedCanvasKeepsThePreferences() { |
There was a problem hiding this comment.
The test only checks the background color. Could it also check the font (the part that threw Widget is disposed), and, with the fix above, that setInvertedColors(true) survives setupTerminal()?
There was a problem hiding this comment.
The test now also checks the font (the part that threw "Widget is disposed"), and a new test sets the inverted colors and a buffer line limit of 123 on the terminal, recreates it and checks both stay. On master all three tests fail with "Widget is disposed"; on the previous head of this PR the new one failed on the inverted colors.
d17d8a4 to
c069116
Compare
|
@insjang If you have access to copilot please request new review from it after you push new version, that would shorten the loop as you would be able to handle multiple reviews till I look into it again. |
Dragging a terminal tab to another terminals view recreates the terminal controls in the new view. This failed in two ways: - The text line renderer of the new canvas measured the font on fCtlText, which at that point still is the canvas that was just disposed. The move stopped with "Widget is disposed", leaving the tab behind and both terminals blank. - The preferences were only applied to freshly created terminals, so a moved terminal fell back to the default colors and font. setupTerminal() now drops fCtlText with the old parent, so the renderer measures on the display until the new canvas exists. A moved terminal gets the colors and the font from the preferences (the defaults when it has no preference store), and keeps what was set on it alone: the inverted colors of its context menu, and the buffer line limit a client may have set through ITerminalViewControl. TerminalControlRecreateUITest recreates the controls in a new parent and checks the background color, the font, the inverted colors and the buffer line limit, and the inverted colors of a terminal made without a preference store; on master the tests fail with "Widget is disposed". It disposes the terminal afterwards, as the terminals view does when a tab is closed, and reads the background color through the renderer, whose getter is public.
c069116 to
783a360
Compare
|
Thanks, will do. I re-requested a Copilot review on 783a360 and will do so after each push from now on. |
In that case it might be best to even run copilot review in a PR in your own repo so the PRs you open here are truly "ready". |
akurtakov
left a comment
There was a problem hiding this comment.
Thanks, all addressed: a moved terminal keeps its inverted colors (also without a preference store) and its buffer line limit, gets the colors and font from the preferences, and the renderer no longer touches the disposed canvas. The new tests cover each of these and fail without the fix.
Tested manually: inverted the colors of a terminal from its context menu, with the global preference off, and dragged its tab to a second Terminals view; it arrived inverted, with the right font and colors and no "Widget is disposed".
|
Good idea, thanks. I'll set up Copilot review on my fork and run it on each branch there before opening or updating a PR here. |


Dragging a terminal tab to another terminals view (the view's "New Terminal View" button, then drag a tab across) currently fails:
SWTException: Widget is disposed, thrown fromStyleMap.updateFontviaVT100TerminalControl.setupTerminal.Cause
setupTerminal(Composite)recreates the controls in the new parent. TheTextLineRendererof the new canvas measures the font onfCtlText, but at that pointfCtlTextis still the canvas that was just disposed.A second problem shows once that is fixed: the preferences (colors, font, buffer size) were only applied to freshly created terminals, so a moved terminal fell back to the default colors and font.
Fix
setupTerminalapplies the preferences to recreated controls too. The property change listener is still added only once.Test
TerminalControlRecreateUITestrecreates a terminal in a new parent, as the drag and drop does:The existing terminal tests pass.