diff --git a/terminal/bundles/org.eclipse.terminal.control/META-INF/MANIFEST.MF b/terminal/bundles/org.eclipse.terminal.control/META-INF/MANIFEST.MF index ff5a3fb72be..0c618bbd154 100644 --- a/terminal/bundles/org.eclipse.terminal.control/META-INF/MANIFEST.MF +++ b/terminal/bundles/org.eclipse.terminal.control/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.terminal.control; singleton:=true -Bundle-Version: 1.1.200.qualifier +Bundle-Version: 1.1.300.qualifier Bundle-Activator: org.eclipse.terminal.internal.control.impl.TerminalPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/emulator/VT100TerminalControl.java b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/emulator/VT100TerminalControl.java index e80d897f11c..8fa24651171 100644 --- a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/emulator/VT100TerminalControl.java +++ b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/emulator/VT100TerminalControl.java @@ -657,9 +657,12 @@ public void setupTerminal(Composite parent) { setupControls(parent); setCommandInputField(fCommandInputField); setupListeners(); - if (fPreferenceStore != null && wasDisposed) { + if (fPreferenceStore != null) { + // new controls after a drag and drop need the colors and font as well updatePreferences(null); - fPreferenceStore.addPropertyChangeListener(fPreferenceListener); + if (wasDisposed) { + fPreferenceStore.addPropertyChangeListener(fPreferenceListener); + } } JFaceResources.getFontRegistry().addListener(fFontListener); setupHelp(fWndParent, TerminalPlugin.HELP_VIEW); @@ -763,7 +766,10 @@ protected void setupControls(Composite parent) { snapshot.updateSnapshot(false); fPollingTextCanvasModel = new PollingTextCanvasModel(snapshot); fCtlText = new TextCanvas(fWndParent, fPollingTextCanvasModel, SWT.NONE, - 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, + fPollingTextCanvasModel)); fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); fCtlText.addResizeHandler((lines, columns) -> fTerminalText.setDimensions(lines, columns)); diff --git a/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/internal/textcanvas/TerminalControlRecreateUITest.java b/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/internal/textcanvas/TerminalControlRecreateUITest.java new file mode 100644 index 00000000000..f21ca7433eb --- /dev/null +++ b/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/internal/textcanvas/TerminalControlRecreateUITest.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2026 Eclipse contributors and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.terminal.internal.textcanvas; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.terminal.connector.ITerminalConnector; +import org.eclipse.terminal.connector.TerminalState; +import org.eclipse.terminal.control.ITerminalListener; +import org.eclipse.terminal.control.TerminalTitleRequestor; +import org.eclipse.terminal.internal.emulator.VT100TerminalControl; +import org.eclipse.terminal.internal.preferences.ITerminalConstants; +import org.eclipse.terminal.model.TerminalColor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests recreating the terminal controls in a new parent, as moving a terminal tab to another + * terminals view does. + */ +public class TerminalControlRecreateUITest { + + private static final RGB BACKGROUND = new RGB(1, 2, 3); + + private Display display; + private Shell shell; + private VT100TerminalControl terminal; + + @BeforeEach + public void createTerminal() { + display = Display.getCurrent() != null ? null : new Display(); + shell = new Shell(); + shell.setLayout(new FillLayout()); + PreferenceStore preferences = new PreferenceStore(); + preferences.setValue(ITerminalConstants.getPrefForTerminalColor(TerminalColor.BACKGROUND), + "1,2,3"); //$NON-NLS-1$ + ITerminalListener listener = new ITerminalListener() { + @Override + public void setState(TerminalState state) { + } + + @Override + public void setTerminalSelectionChanged() { + } + + @Override + public void setTerminalTitle(String title, TerminalTitleRequestor requestor) { + } + }; + terminal = new VT100TerminalControl(listener, new Composite(shell, 0), new ITerminalConnector[0], preferences); + } + + @AfterEach + public void dispose() { + // as the terminals view does when a terminal tab is closed + terminal.disposeTerminal(); + shell.dispose(); + if (display != null) { + display.dispose(); + } + } + + private void recreateInNewParent() { + terminal.setupTerminal(new Composite(shell, 0)); + } + + @Test + public void recreatingDoesNotUseTheDisposedCanvas() { + assertDoesNotThrow(this::recreateInNewParent); + } + + @Test + public void recreatedCanvasKeepsThePreferences() { + assertEquals(BACKGROUND, ((TextCanvas) terminal.getControl()).getCellRenderer().getDefaultBackgroundColor().getRGB()); + recreateInNewParent(); + assertEquals(BACKGROUND, ((TextCanvas) terminal.getControl()).getCellRenderer().getDefaultBackgroundColor().getRGB()); + } +} diff --git a/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/test/AutomatedTestSuite.java b/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/test/AutomatedTestSuite.java index c146029c61a..05bd86f43c3 100644 --- a/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/test/AutomatedTestSuite.java +++ b/terminal/tests/org.eclipse.terminal.test/src/org/eclipse/terminal/test/AutomatedTestSuite.java @@ -25,6 +25,7 @@ org.eclipse.terminal.model.AllTestSuite.class, // org.eclipse.terminal.internal.connector.TerminalConnectorTest.class, // org.eclipse.terminal.internal.connector.TerminalToRemoteInjectionOutputStreamTest.class, // + org.eclipse.terminal.internal.textcanvas.TerminalControlRecreateUITest.class, // org.eclipse.terminal.view.ui.tests.TerminalsViewReorderTest.class, // }) public class AutomatedTestSuite {