mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-197188 Fix fallback Switcher hint popup update
PSI_ELEMENT.getData returns an outdated PSI element if called in-place in the same EDT event the selection changes. Fix by postponing the update using a state flow. GitOrigin-RevId: 29ce5db2492e14974887b68b2f044bd2f18de8f9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
51e12aea9e
commit
186ffa6182
@@ -21,9 +21,13 @@ import com.intellij.ide.util.gotoByName.QuickSearchComponent
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.UiDispatcherKind
|
||||
import com.intellij.openapi.application.ui
|
||||
import com.intellij.openapi.application.writeIntentReadAction
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory
|
||||
@@ -67,8 +71,12 @@ import com.intellij.util.ui.StartupUiUtil
|
||||
import com.intellij.util.ui.SwingTextTrimmer
|
||||
import com.intellij.util.ui.accessibility.ScreenReader
|
||||
import com.intellij.util.ui.components.BorderLayoutPanel
|
||||
import com.intellij.util.ui.launchOnShow
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.NonNls
|
||||
@@ -279,6 +287,7 @@ object Switcher : BaseSwitcherAction(null) {
|
||||
pinned = recent,
|
||||
)
|
||||
resetListModelAndUpdateNames(filesModel, filesToShow)
|
||||
val selectedItemFlow = MutableStateFlow<SwitcherListItem?>(null)
|
||||
val filesSelectionListener = object : ListSelectionListener {
|
||||
override fun valueChanged(e: ListSelectionEvent) {
|
||||
if (e.valueIsAdjusting) {
|
||||
@@ -286,9 +295,26 @@ object Switcher : BaseSwitcherAction(null) {
|
||||
}
|
||||
|
||||
updatePathLabel()
|
||||
val hint = hint
|
||||
val popupUpdater = if (hint == null || !hint.isVisible) null else hint.getUserData(PopupUpdateProcessorBase::class.java)
|
||||
popupUpdater?.updatePopup(CommonDataKeys.PSI_ELEMENT.getData(DataManager.getInstance().getDataContext(this@SwitcherPanel)))
|
||||
selectedItemFlow.value = selectedList?.selectedValue
|
||||
}
|
||||
}
|
||||
launchOnShow("Switcher hint popup updates") {
|
||||
selectedItemFlow.collectLatest { selectedValue ->
|
||||
// launchOnShow uses UI, but it won't do here: updatePopup needs a WIRA.
|
||||
// Still, we'd like to avoid locking until the updatePopup call.
|
||||
// At the same time, we'd like to keep this whole thing in a single EDT event,
|
||||
// otherwise there's a chance that the hint popup may be hidden in between.
|
||||
// So we can't just switch to Dispatchers.EDT, as that will dispatch on a separate event.
|
||||
// Therefore, we use RELAX and take the lock only when necessary.
|
||||
withContext(Dispatchers.ui(UiDispatcherKind.RELAX)) {
|
||||
val hint = hint
|
||||
val popupUpdater = if (hint == null || !hint.isVisible) null else hint.getUserData(PopupUpdateProcessorBase::class.java)
|
||||
if (selectedValue != null && popupUpdater != null) {
|
||||
writeIntentReadAction {
|
||||
popupUpdater.updatePopup(CommonDataKeys.PSI_ELEMENT.getData(DataManager.getInstance().getDataContext(this@SwitcherPanel)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user