From 8ec8ea62b2e62e4695696002090c40d6840f9252 Mon Sep 17 00:00:00 2001 From: Konstantin Nisht Date: Mon, 30 Jun 2025 17:09:09 +0200 Subject: [PATCH] [threading] IJPL-192699 IJ-CR-166168: Prevent possible NPE with absent root pane GitOrigin-RevId: d6df9bde5dd6b538f8680035927cdf43381ca0f1 --- .../openapi/progress/util/SuvorovProgress.kt | 12 ++++++------ .../openapi/progress/util/ui/NiceOverlayUi.kt | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/SuvorovProgress.kt b/platform/platform-impl/src/com/intellij/openapi/progress/util/SuvorovProgress.kt index be91dbd76a37..f274ff792ca8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/SuvorovProgress.kt +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/SuvorovProgress.kt @@ -26,7 +26,6 @@ import kotlinx.coroutines.future.asCompletableFuture import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.Nls import java.awt.AWTEvent -import java.awt.Component import java.awt.KeyboardFocusManager import java.awt.event.InvocationEvent import java.awt.event.KeyEvent @@ -34,6 +33,7 @@ import java.awt.event.MouseEvent import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.atomic.AtomicReference import javax.swing.JFrame +import javax.swing.JRootPane import javax.swing.SwingUtilities /** @@ -107,12 +107,12 @@ object SuvorovProgress { processInvocationEventsWithoutDialog(awaitedValue, Int.MAX_VALUE) } "NiceOverlay" -> { - val currentFocusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusOwner - if (currentFocusOwner == null) { + val currentFocusedPane = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusOwner?.let(SwingUtilities::getRootPane) + if (currentFocusedPane == null) { // can happen also in tests processInvocationEventsWithoutDialog(awaitedValue, Int.MAX_VALUE) } else { - showNiceOverlay(awaitedValue, currentFocusOwner) + showNiceOverlay(awaitedValue, currentFocusedPane) } } "Bar", "Overlay" -> showPotemkinProgress(awaitedValue, isBar = value == "Bar") @@ -120,8 +120,8 @@ object SuvorovProgress { } } - private fun showNiceOverlay(awaitedValue: Deferred<*>, currentFocusOwner: Component) { - val niceOverlay = NiceOverlayUi(currentFocusOwner, false) + private fun showNiceOverlay(awaitedValue: Deferred<*>, rootPane: JRootPane) { + val niceOverlay = NiceOverlayUi(rootPane, false) val disposable = Disposer.newDisposable() val stealer = PotemkinProgress.startStealingInputEvents( diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ui/NiceOverlayUi.kt b/platform/platform-impl/src/com/intellij/openapi/progress/util/ui/NiceOverlayUi.kt index 520feefee75c..b181cc41abaa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ui/NiceOverlayUi.kt +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ui/NiceOverlayUi.kt @@ -36,7 +36,7 @@ import javax.swing.UIManager */ @ApiStatus.Internal class NiceOverlayUi( - component: Component, + val rootPane: JRootPane, /** * "Close" button requires making a screenshot (see [com.intellij.openapi.progress.util.ui.NiceOverlayUi.screenshot]) * The screenshot via Robot provokes an alert on MacOS, and it does not work nice on multi-monitor linux setup @@ -44,7 +44,6 @@ class NiceOverlayUi( */ val showCloseButton: Boolean, ) { - private val rootPane: JRootPane = SwingUtilities.getRootPane(component) private val mainText = DiagnosticBundle.message("freeze.popup.application.is.not.responding", ApplicationInfo.getInstance().versionName)