diff --git a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/CopyOnSelectionHandler.kt b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/CopyOnSelectionHandler.kt index a4e09dc58f93..c90e73985dc4 100644 --- a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/CopyOnSelectionHandler.kt +++ b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/CopyOnSelectionHandler.kt @@ -43,7 +43,7 @@ internal class CopyOnSelectionHandler private constructor(private val settings: // Only perform copying if the editor is focused. // In most cases it is, but if the selection was updated through the API it may not be the case. if (!settings.copyOnSelect() || e.editor?.contentComponent?.isFocusOwner != true) return - val text = e.editor.selectionModel.selectedText ?: return + val text = e.editor.selectionModel.getSelectedText(true) ?: return copy(text) } } diff --git a/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/TerminalCopyOnSelectionTest.kt b/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/TerminalCopyOnSelectionTest.kt new file mode 100644 index 000000000000..a4da5120f9b1 --- /dev/null +++ b/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/TerminalCopyOnSelectionTest.kt @@ -0,0 +1,90 @@ +package com.intellij.terminal.tests.reworked.frontend + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.LogicalPosition +import com.intellij.openapi.ide.CopyPasteManager +import com.intellij.openapi.util.Disposer +import com.intellij.platform.util.coroutines.childScope +import com.intellij.psi.PsiDocumentManager +import com.intellij.terminal.JBTerminalSystemSettingsProviderBase +import com.intellij.terminal.frontend.view.impl.TerminalEditorFactory +import com.intellij.testFramework.fixtures.BasePlatformTestCase +import kotlinx.coroutines.cancel +import org.jetbrains.plugins.terminal.block.reworked.lang.TerminalOutputPsiFile +import org.jetbrains.plugins.terminal.util.terminalProjectScope +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import java.awt.Component +import java.awt.KeyboardFocusManager +import java.awt.datatransfer.DataFlavor +import javax.swing.FocusManager + +@RunWith(JUnit4::class) +internal class TerminalCopyOnSelectionTest : BasePlatformTestCase() { + private var defaultFocusManager: KeyboardFocusManager? = null + + override fun setUp() { + super.setUp() + defaultFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager() + } + + override fun tearDown() { + try { + KeyboardFocusManager.setCurrentKeyboardFocusManager(defaultFocusManager) + } + catch (e: Throwable) { + addSuppressedException(e) + } + finally { + super.tearDown() + } + } + + @Test + fun `copy on selection copies block selection from all selected lines`() { + val editor = createTerminalEditor() + editor.emitOnTerminal( + """ + first + second + third + """.trimIndent() + ) + + editor.selectionModel.setBlockSelection(LogicalPosition(0, 1), LogicalPosition(2, 4)) + + val transferable = copiedTransferable() + assertNotNull(transferable) + assertEquals("irs\neco\nhir", transferable!!.getTransferData(DataFlavor.stringFlavor)) + } + + private fun createTerminalEditor(): Editor { + val scope = terminalProjectScope(project).childScope("TerminalOutputEditor").also { + Disposer.register(testRootDisposable) { it.cancel() } + } + val editor = TerminalEditorFactory.createOutputEditor( + project, + object : JBTerminalSystemSettingsProviderBase() { + override fun copyOnSelect(): Boolean = true + }, + scope + ) + // Copy on selection only works if terminal is the focus owner. + KeyboardFocusManager.setCurrentKeyboardFocusManager( + object : FocusManager() { + override fun getFocusOwner(): Component = editor.contentComponent + } + ) + return editor + } + + private fun Editor.emitOnTerminal(text: String) { + document.setText(text) + val psiFile = PsiDocumentManager.getInstance(this@TerminalCopyOnSelectionTest.project).getPsiFile(this.document) as TerminalOutputPsiFile + psiFile.charsSequence = this.document.immutableCharSequence + } + + private fun copiedTransferable() = + CopyPasteManager.getInstance().let { it.systemSelectionContents ?: it.contents } +}