[threading] IJPL-192699: Do not draw close button in NiceOverlayUi

This is a temporary compromise in order to release the new UI, but limit its functionality until the propert API for screenshots arrives from JBR

GitOrigin-RevId: 9e6656eb74c492a07edaaa6a17a2601c447e0466
This commit is contained in:
Konstantin Nisht
2025-06-30 21:19:18 +00:00
committed by intellij-monorepo-bot
parent 643d181dc4
commit db6e1b33d2
2 changed files with 41 additions and 12 deletions
@@ -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(
@@ -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()