From c50cb61de5621af7035e7f49afc2b0cd6f76cbe9 Mon Sep 17 00:00:00 2001 From: Konstantin Hudyakov Date: Thu, 20 Nov 2025 15:18:14 +0200 Subject: [PATCH] [terminal] IJPL-214752 Fix losing focus when resizing nano `nano` is crazy - it emits alternate buffer switch events on resize. So, we receive alternate buffer disabling event and then enabling in a row. When we receive alternate buffer switch event - we add the current editor to the UI hierarchy and request focus to the new editor if terminal was focused previously. For some reason when we received alternate buffer enabled event (after disabling), the focus switch from the disabling event was not yet performed, so `terminalPanel.isFocusAncestor()` was false. This way focus was lost. Fixed it by refactoring the StateFlow listening, though, don't really understand why it works correctly now. Previous and new implementations should work the same. GitOrigin-RevId: 983d1eff70e1c4012238a8dc314ddd9164c62734 --- .../frontend/view/impl/TerminalViewImpl.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt index c1630c64928b..c06ff74d2f54 100644 --- a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt +++ b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt @@ -406,19 +406,21 @@ class TerminalViewImpl( } private fun listenAlternateBufferSwitch() { - coroutineScope.launch(Dispatchers.EDT + ModalityState.any().asContextElement() + CoroutineName("Alternate buffer switch listener")) { + coroutineScope.launch(CoroutineName("Alternate buffer switch listener")) { sessionModel.terminalState.collect { state -> - if (state.isAlternateScreenBuffer != isAlternateScreenBuffer) { - isAlternateScreenBuffer = state.isAlternateScreenBuffer + withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) { + if (state.isAlternateScreenBuffer != isAlternateScreenBuffer) { + isAlternateScreenBuffer = state.isAlternateScreenBuffer - val terminalWasFocused = terminalPanel.isFocusAncestor() - val editor = if (state.isAlternateScreenBuffer) alternateBufferEditor else outputEditor - terminalPanel.setTerminalContent(editor) - terminalSearchController.finishSearchSession() - mutableOutputModels.setActiveModel(state.isAlternateScreenBuffer) + val terminalWasFocused = terminalPanel.isFocusAncestor() + val editor = if (state.isAlternateScreenBuffer) alternateBufferEditor else outputEditor + terminalPanel.setTerminalContent(editor) + terminalSearchController.finishSearchSession() + mutableOutputModels.setActiveModel(state.isAlternateScreenBuffer) - if (terminalWasFocused) { - IdeFocusManager.getInstance(project).requestFocus(terminalPanel.preferredFocusableComponent, true) + if (terminalWasFocused) { + IdeFocusManager.getInstance(project).requestFocus(terminalPanel.preferredFocusableComponent, true) + } } } }