[terminal] IJPL-165734 Fix restarting Classic Terminal session when moving editor tab

(cherry picked from commit f0775eb1e0e660ae3ca05c9074e7eb1b763efa27)

IJ-CR-210789

GitOrigin-RevId: f9de82e34c6f49d80fc4f19333995b2e3e3c748b
This commit is contained in:
Konstantin Hudyakov
2026-07-13 17:14:42 +00:00
committed by intellij-monorepo-bot
parent 66eb35e28e
commit 051688f94d
3 changed files with 7 additions and 27 deletions
@@ -14,6 +14,7 @@ import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.terminal.JBTerminalWidget;
import com.intellij.terminal.ui.TerminalWidgetKt;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.jediterm.terminal.ui.TerminalWidgetListener;
import kotlinx.coroutines.CoroutineScope;
import org.jetbrains.annotations.ApiStatus;
@@ -23,6 +24,7 @@ import org.jetbrains.plugins.terminal.util.TerminalCoroutineKt;
import javax.swing.JComponent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.TimeUnit;
@ApiStatus.Internal
public final class ClassicTerminalSessionEditor extends UserDataHolderBase implements FileEditor {
@@ -103,7 +105,7 @@ public final class ClassicTerminalSessionEditor extends UserDataHolderBase imple
termWidget.removeListener(myListener);
}
if (Boolean.TRUE.equals(myFile.getUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN))) {
ApplicationManager.getApplication().invokeLater(() -> {
AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> {
boolean disposedBefore = Disposer.isDisposed(myFile.getTerminalWidget());
Disposer.dispose(myWidgetParentDisposable);
boolean disposedAfter = Disposer.isDisposed(myFile.getTerminalWidget());
@@ -111,7 +113,7 @@ public final class ClassicTerminalSessionEditor extends UserDataHolderBase imple
LOG.error(JBTerminalWidget.class.getSimpleName() + " parent disposable hasn't been changed " +
"(disposed before: " + disposedBefore + ", disposed after: " + disposedAfter + ")");
}
});
}, 1000, TimeUnit.MILLISECONDS);
}
else {
Disposer.dispose(myWidgetParentDisposable);
@@ -1,21 +1,13 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.terminal.vfs;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorPolicy;
import com.intellij.openapi.fileEditor.FileEditorProvider;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.terminal.ui.TerminalWidget;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.terminal.LocalTerminalDirectRunner;
import org.jetbrains.plugins.terminal.ShellStartupOptions;
import org.jetbrains.plugins.terminal.ShellStartupOptionsKt;
import org.jetbrains.plugins.terminal.arrangement.TerminalWorkingDirectoryManager;
final class ClassicTerminalSessionEditorProvider implements FileEditorProvider, DumbAware {
@Override
@@ -31,23 +23,7 @@ final class ClassicTerminalSessionEditorProvider implements FileEditorProvider,
@Override
public @NotNull FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) {
TerminalSessionVirtualFileImpl terminalFile = (TerminalSessionVirtualFileImpl)file;
if (file.getUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN) != null) {
return new ClassicTerminalSessionEditor(project, terminalFile);
}
else {
TerminalWidget widget = terminalFile.getTerminalWidget();
String workingDirectory = TerminalWorkingDirectoryManager.getWorkingDirectory(widget);
Disposable tempDisposable = Disposer.newDisposable();
ShellStartupOptions options = ShellStartupOptionsKt.shellStartupOptions(workingDirectory);
TerminalWidget newWidget = new LocalTerminalDirectRunner(project).startShellTerminalWidget(tempDisposable, options, true);
TerminalSessionVirtualFileImpl newSessionVirtualFile = new TerminalSessionVirtualFileImpl(terminalFile.getName(),
newWidget,
terminalFile.getSettingsProvider());
ClassicTerminalSessionEditor editor = new ClassicTerminalSessionEditor(project, newSessionVirtualFile);
Disposer.dispose(tempDisposable); // newWidget's parent disposable should be changed now
return editor;
}
return new ClassicTerminalSessionEditor(project, terminalFile);
}
@Override
@@ -1,6 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.terminal.vfs;
import com.intellij.openapi.fileEditor.FileEditorManagerKeys;
import com.intellij.terminal.ui.TerminalWidget;
import com.intellij.testFramework.LightVirtualFile;
import com.jediterm.terminal.ui.settings.SettingsProvider;
@@ -19,6 +20,7 @@ public final class TerminalSessionVirtualFileImpl extends LightVirtualFile {
@NotNull SettingsProvider settingsProvider) {
myTerminalWidget = terminalWidget;
mySettingsProvider = settingsProvider;
putUserData(FileEditorManagerKeys.FORBID_TAB_SPLIT, true);
setFileType(ClassicTerminalSessionFileType.INSTANCE);
setWritable(true);
try {