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 9becf6141c0c..be91dbd76a37 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 @@ -28,11 +28,11 @@ import org.jetbrains.annotations.Nls import java.awt.AWTEvent import java.awt.Component import java.awt.KeyboardFocusManager -import java.util.concurrent.atomic.AtomicReference import java.awt.event.InvocationEvent import java.awt.event.KeyEvent import java.awt.event.MouseEvent import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.atomic.AtomicReference import javax.swing.JFrame import javax.swing.SwingUtilities @@ -121,7 +121,7 @@ object SuvorovProgress { } private fun showNiceOverlay(awaitedValue: Deferred<*>, currentFocusOwner: Component) { - val niceOverlay = NiceOverlayUi(currentFocusOwner) + val niceOverlay = NiceOverlayUi(currentFocusOwner, 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 d29e6d6c96db..520feefee75c 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 @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nls import java.awt.* import java.awt.event.InputEvent import java.awt.event.KeyEvent +import java.awt.image.BaseMultiResolutionImage import java.awt.image.BufferedImage import java.awt.image.MultiResolutionImage import javax.swing.JRootPane @@ -34,7 +35,15 @@ import javax.swing.UIManager * We have to use AWT here, as we cannot spin the EventQueue for Swing */ @ApiStatus.Internal -class NiceOverlayUi(component: Component) { +class NiceOverlayUi( + component: Component, + /** + * "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 + * So for now we decide to not show the close button and release at least some part of the UI. + */ + val showCloseButton: Boolean, +) { private val rootPane: JRootPane = SwingUtilities.getRootPane(component) @@ -69,7 +78,14 @@ class NiceOverlayUi(component: Component) { private val currentFontMetrics: FontMetrics = GraphicsUtil.safelyGetGraphics(rootPane).getFontMetrics(font) private val yOffsetOfTextInPopup: Int = popupHeight / 2 + currentFontMetrics.ascent / 2 - JBUIScale.scale(1) - private val popupWidth: Int = horizontalInset + getTextLength(mainText) + getTextLength(dumpThreadsButtonText) + getTextLength(dumpThreadsButtonShortcutText) + gapBetweenText1AndText2 + gapBetweenText2AndText3 + separatorInset + 1 + separatorInset + closeIconLength + horizontalInset + private val popupWidth: Int = horizontalInset + getTextLength(mainText) + gapBetweenText1AndText2 + getTextLength(dumpThreadsButtonText) + gapBetweenText2AndText3 + getTextLength(dumpThreadsButtonShortcutText) + + if (showCloseButton) { + separatorInset + 1 + separatorInset + closeIconLength + } + else { + 0 + } + + horizontalInset // offsets relative to the containing component private val popupOffsetX: Int = rootPane.width / 2 - popupWidth / 2 @@ -105,7 +121,13 @@ class NiceOverlayUi(component: Component) { private var closed = false init { - screenshot = takeScreenshot() + screenshot = if (showCloseButton) { + takeScreenshot() + } + else { + // screenshot is not accessed in this case + BaseMultiResolutionImage(BufferedImage(0, 0, BufferedImage.TYPE_INT_ARGB)) + } drawShadow() @@ -190,7 +212,7 @@ class NiceOverlayUi(component: Component) { * @param point the point relative to the containing component */ fun mouseMoved(point: Point) { - closeButtonHovered = locationOfCross.contains(point) + closeButtonHovered = showCloseButton && locationOfCross.contains(point) threadDumpButtonHovered = locationOfThreadDumpButton.contains(point) } @@ -204,7 +226,7 @@ class NiceOverlayUi(component: Component) { * @param point the point relative to the containing component */ fun mouseClicked(point: Point): ClickOutcome { - if (locationOfCross.contains(point)) { + if (showCloseButton && locationOfCross.contains(point)) { closed = true restoreScreenshot() return ClickOutcome.CLOSED @@ -218,6 +240,9 @@ class NiceOverlayUi(component: Component) { } private fun restoreScreenshot() { + check(showCloseButton) { + "Screenshot can be used only when the close button is enabled" + } val innerGraphics = GraphicsUtil.safelyGetGraphics(rootPane) as Graphics2D try { val variant = screenshot.resolutionVariants.run { if (size > 1) get(1) else get(0) } @@ -267,14 +292,18 @@ class NiceOverlayUi(component: Component) { graphics.drawMainText(accumulatingOffsetX, dumpThreadsButtonText) accumulatingOffsetX += lengthOfText2 + gapBetweenText2AndText3 accumulatingOffsetX += graphics.drawShortcut(accumulatingOffsetX, dumpThreadsButtonShortcutText) - accumulatingOffsetX += graphics.drawSeparator(accumulatingOffsetX) - graphics.color = fgColor + if (showCloseButton) { + accumulatingOffsetX += graphics.drawSeparator(accumulatingOffsetX) - if (closeButtonHovered) { - graphics.paintButtonBackground(accumulatingOffsetX, closeIconLength) + graphics.color = fgColor + + if (closeButtonHovered) { + graphics.paintButtonBackground(accumulatingOffsetX, closeIconLength) + } + graphics.drawCloseButton(accumulatingOffsetX) } - graphics.drawCloseButton(accumulatingOffsetX) + } finally { graphics.dispose()