From 87a6c8dae25c6f843f9bd04568707c73f578f2d5 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 16 Feb 2017 17:52:34 +0300 Subject: [PATCH] IDEA-168315 Component.getGraphics() should not be used to get scale for the HiDPI API Additionally: HiDPI API methods renaming. --- .../src/com/intellij/ide/ui/UISettings.kt | 4 +- .../colors/impl/AbstractColorsScheme.java | 4 +- .../console/ConsoleGutterComponent.java | 2 +- .../src/com/intellij/find/SearchTextArea.java | 10 +- .../openapi/util/DimensionService.java | 9 +- .../com/intellij/ui/paint/EffectPainter.java | 2 +- .../ide/RecentProjectsManagerBase.java | 6 +- .../ide/plugins/PluginsTableRenderer.java | 2 +- .../ide/ui/laf/darcula/DarculaLaf.java | 4 +- .../laf/darcula/ui/DarculaRadioButtonUI.java | 2 +- .../src/com/intellij/ide/util/TipUIUtil.java | 12 +- .../impl/EditorGutterComponentImpl.java | 12 +- .../openapi/editor/impl/ImmediatePainter.java | 2 +- .../editor/impl/view/EditorPainter.java | 2 +- .../openapi/wm/impl/WindowManagerImpl.java | 33 ++- .../wm/impl/status/MemoryUsagePanel.java | 4 +- .../welcomeScreen/RecentProjectPanel.java | 4 +- .../src/com/intellij/ui/BalloonImpl.java | 20 +- .../com/intellij/openapi/util/IconLoader.java | 28 +-- .../src/com/intellij/util/ImageLoader.java | 10 +- .../com/intellij/util/JBHiDPIScaledImage.java | 24 +- .../src/com/intellij/util/RetinaImage.java | 13 +- .../util/src/com/intellij/util/ui/JBUI.java | 205 ++++++++---------- .../util/src/com/intellij/util/ui/UIUtil.java | 98 +++++---- 24 files changed, 261 insertions(+), 251 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt index f62e9d2d5389..a8e7a98ed66c 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.kt @@ -229,8 +229,8 @@ class UISettings : BaseState(), PersistentStateComponent { } if (fontScale <= 0) { - // Reset font to default on switch from IDEA-managed HiDPI to JDK-managed HiDPI. Doesn't affect OSX. - if (UIUtil.isJDKManagedHiDPI() && !SystemInfo.isMac) fontSize = UIUtil.DEF_SYSTEM_FONT_SIZE.toInt() + // Reset font to default on switch from IDEA-managed HiDPI to JRE-managed HiDPI. Doesn't affect OSX. + if (UIUtil.isJreHiDPIEnabled() && !SystemInfo.isMac) fontSize = UIUtil.DEF_SYSTEM_FONT_SIZE.toInt() } else { fontSize = JBUI.scale(fontSize / fontScale).toInt() diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index fd8df084f92e..c0ba5adbe121 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -561,8 +561,8 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion)); /** - * FONT_SCALE is used to correctly identify the font size in both the JDK-managed HiDPI mode and - * the IDE-managed HiDPI mode: {@link UIUtil#isJDKManagedHiDPI()}. Also, it helps to distinguish + * FONT_SCALE is used to correctly identify the font size in both the JRE-managed HiDPI mode and + * the IDE-managed HiDPI mode: {@link UIUtil#isJreHiDPIEnabled()}. Also, it helps to distinguish * the "hidpi-aware" scheme version from the previous one. Namely, the absence of the FONT_SCALE * attribute in the scheme indicates the previous "hidpi-unaware" scheme and the restored font size * is reset to default. It's assumed this (transition case) happens only once, after which the IDE diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java index 83a8bb25dfba..099b5bbf0730 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java @@ -156,7 +156,7 @@ class ConsoleGutterComponent extends JComponent implements MouseMotionListener { Graphics2D g2 = (Graphics2D)g; Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - if (!UIUtil.isJDKManagedHiDPIScreen(g2)) { + if (!UIUtil.isJreHiDPI(this)) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } diff --git a/platform/lang-impl/src/com/intellij/find/SearchTextArea.java b/platform/lang-impl/src/com/intellij/find/SearchTextArea.java index 8c628390320a..54c328742b4c 100644 --- a/platform/lang-impl/src/com/intellij/find/SearchTextArea.java +++ b/platform/lang-impl/src/com/intellij/find/SearchTextArea.java @@ -108,8 +108,10 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList public Insets getBorderInsets(Component c) { int bottom = (StringUtil.getLineBreakCount(myTextArea.getText()) > 0) ? 2 : UIUtil.isUnderDarcula() ? 1 : 0; int top = myTextArea.getFontMetrics(myTextArea.getFont()).getHeight() <= 16 ? 2 : 1; - if (JBUI.isHiDPI(c)) bottom = 2; - if (JBUI.isHiDPI(c)) top = 2; + if (JBUI.isUsrHiDPI()) { + bottom = 2; + top = 2; + } return new JBInsets(top, 0, bottom, 0); } @@ -357,13 +359,13 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList @Override String getHistoryButtonConstraints() { int extraGap = getExtraGap(); - return "ay top, gaptop " + extraGap + ", gapleft" + (JBUI.isHiDPI(myTextArea) ? 4 : 0); + return "ay top, gaptop " + extraGap + ", gapleft" + (JBUI.isUsrHiDPI() ? 4 : 0); } private int getExtraGap() { int height = UIUtil.getLineHeight(myTextArea); Insets insets = myTextArea.getInsets(); - return Math.max(JBUI.isHiDPI(myTextArea) ? 0 : 1, (height + insets.top + insets.bottom - JBUI.scale(16)) / 2); + return Math.max(JBUI.isUsrHiDPI() ? 0 : 1, (height + insets.top + insets.bottom - JBUI.scale(16)) / 2); } diff --git a/platform/platform-api/src/com/intellij/openapi/util/DimensionService.java b/platform/platform-api/src/com/intellij/openapi/util/DimensionService.java index d35c060f8b81..30285694958f 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/DimensionService.java +++ b/platform/platform-api/src/com/intellij/openapi/util/DimensionService.java @@ -25,7 +25,6 @@ import com.intellij.openapi.wm.WindowManager; import com.intellij.ui.ScreenUtil; import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.JBUI.ScaleType; import com.intellij.util.ui.UIUtil; import gnu.trove.TObjectIntHashMap; import org.jdom.Element; @@ -312,15 +311,15 @@ public class DimensionService implements PersistentStateComponent { screen = gd.getDefaultConfiguration().getBounds(); } float scale = 1f; - if (UIUtil.isJDKManagedHiDPI()) { - scale = JBUI.sysScale(gd); + if (UIUtil.isJreHiDPIEnabled()) { + scale = JBUI.sysScale(gd.getDefaultConfiguration()); // normalize screen bounds screen.setBounds((int)Math.floor(screen.x * scale), (int)Math.floor(screen.y * scale), (int)Math.ceil(screen.width * scale), (int)Math.ceil(screen.height * scale)); } String realKey = key + '.' + screen.x + '.' + screen.y + '.' + screen.width + '.' + screen.height; - if (JBUI.isHiDPI(gd, ScaleType.PIX)) { - int dpi = ((int)(96 * JBUI.pixScale(gd))); + if (JBUI.isPixHiDPI(gd.getDefaultConfiguration())) { + int dpi = ((int)(96 * JBUI.pixScale(gd.getDefaultConfiguration()))); realKey += "@" + dpi + "dpi"; } return new Pair<>(realKey, scale); diff --git a/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java b/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java index a2a90f47b960..b69011ff5b61 100644 --- a/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java +++ b/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java @@ -222,7 +222,7 @@ public enum EffectPainter implements RegionPainter { @Override void paintImage(Graphics2D g, int width, int height, int period) { - Integer round = period <= 2 && !UIUtil.isJDKManagedHiDPIScreen(g) ? null : period; + Integer round = period <= 2 && !UIUtil.isJreHiDPI(g != null ? g.getDeviceConfiguration() : null) ? null : period; for (int dx = 0; dx < width; dx += period + period) { RectanglePainter.FILL.paint(g, dx, 0, period, period, round); } diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java index 7969003324f1..74cae4155c2f 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java +++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java @@ -271,7 +271,7 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im @Override public void paintIcon(Component c, Graphics g, int x, int y) { // [tav] todo: the icon is created in def screen scale - if (UIUtil.isJDKManagedHiDPIScreen()) { + if (UIUtil.isJreHiDPI()) { final Graphics2D newG = (Graphics2D)g.create(x, y, image.getWidth(), image.getHeight()); float s = JBUI.sysScale(); newG.scale(1/s, 1/s); @@ -286,12 +286,12 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im @Override public int getIconWidth() { - return UIUtil.isJDKManagedHiDPIScreen() ? (int)(image.getWidth() / JBUI.sysScale()) : image.getWidth(); + return UIUtil.isJreHiDPI() ? (int)(image.getWidth() / JBUI.sysScale()) : image.getWidth(); } @Override public int getIconHeight() { - return UIUtil.isJDKManagedHiDPIScreen() ? (int)(image.getHeight() / JBUI.sysScale()) : image.getHeight(); + return UIUtil.isJreHiDPI() ? (int)(image.getHeight() / JBUI.sysScale()) : image.getHeight(); } }; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java index e343eceffaf0..7614f1720c79 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java @@ -91,7 +91,7 @@ public class PluginsTableRenderer extends DefaultTableCellRenderer { myInfoPanel.remove(myBottomPanel); } - myPanel.setBorder(UIUtil.isJDKManagedHiDPIScreen((Graphics2D)myPanel.getGraphics()) ? new EmptyBorder(4, 3, 4, 3) : new EmptyBorder(2, 3, 2, 3)); + myPanel.setBorder(UIUtil.isJreHiDPI(myPanel) ? new EmptyBorder(4, 3, 4, 3) : new EmptyBorder(2, 3, 2, 3)); } private void createUIComponents() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 1ca09a13b624..89f87ab3beaa 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -183,7 +183,7 @@ public class DarculaLaf extends BasicLookAndFeel { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); } - if (SystemInfo.isLinux && JBUI.isHiDPI()) { + if (SystemInfo.isLinux && JBUI.isUsrHiDPI()) { applySystemFonts(defaults); } defaults.put("EditorPane.font", defaults.getFont("TextField.font")); @@ -237,7 +237,7 @@ public class DarculaLaf extends BasicLookAndFeel { @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") private void patchStyledEditorKit(UIDefaults defaults) { - URL url = getClass().getResource(getPrefix() + (JBUI.isHiDPI() ? "@2x.css" : ".css")); + URL url = getClass().getResource(getPrefix() + (JBUI.isUsrHiDPI() ? "@2x.css" : ".css")); StyleSheet styleSheet = UIUtil.loadStyleSheet(url); defaults.put("StyledEditorKit.JBDefaultStyle", styleSheet); try { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java index 8721199c044c..2b74a6220603 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java @@ -117,7 +117,7 @@ public class DarculaRadioButtonUI extends MetalRadioButtonUI { } if (focus) { - if (UIUtil.isJDKManagedHiDPIScreen(g) || JBUI.isHiDPI(g, JBUI.ScaleType.USR)) { + if (JBUI.isPixHiDPI(c)) { DarculaUIUtil.paintFocusOval(g, JBUI.scale(1), JBUI.scale(1) + 1, w - JBUI.scale(2), h - JBUI.scale(2)); } else { DarculaUIUtil.paintFocusOval(g, 0, JBUI.scale(1), w, h); diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java index 031a7f364816..5d6decaf19cb 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java @@ -32,6 +32,7 @@ import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.impl.DefaultKeymap; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.util.ObjectUtils; import com.intellij.util.ResourceUtil; import com.intellij.util.ui.JBUI; @@ -45,6 +46,7 @@ import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.StringReader; @@ -94,7 +96,7 @@ public class TipUIUtil { StringBuffer text = new StringBuffer(ResourceUtil.loadText(url)); updateShortcuts(text); - updateImages(text, tipLoader); + updateImages(text, tipLoader, browser); String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName()); String major = ApplicationInfo.getInstance().getMajorVersion(); replaced = replaced.replace("&majorVersion;", major); @@ -140,14 +142,16 @@ public class TipUIUtil { } } - private static void updateImages(StringBuffer text, ClassLoader tipLoader) { + private static void updateImages(StringBuffer text, ClassLoader tipLoader, JEditorPane browser) { final boolean dark = UIUtil.isUnderDarcula(); // if (!dark && !retina) { // return; // } String suffix = ""; - if (JBUI.isHiDPI(JBUI.ScaleType.PIX)) suffix += "@2x"; + Component af = IdeFrameImpl.getActiveFrame(); + Component comp = af != null ? af: browser; + if (JBUI.isPixHiDPI(comp)) suffix += "@2x"; if (dark) suffix += "_dark"; int index = text.indexOf(")info -> { Image image = IconUtil.toImage(scaleIcon(getGutterRenderer(info.getPoint()).getIcon())); // [tav] temp workaround for JRE-224 - if (SystemInfo.isWindows && UIUtil.isJDKManagedHiDPI()) { - image = ImageUtil.toBufferedImage(image, !JBUI.isHiDPI((Graphics2D)GraphicsUtil.safelyGetGraphics(myEditor.getComponent()), ScaleType.SYS)); - } + boolean inUserScale = SystemInfo.isWindows ? !UIUtil.isJreHiDPI(myEditor.getComponent()) : true; + image = ImageUtil.toBufferedImage(image, inUserScale); return new DnDImage(image, new Point(image.getWidth(null) / 2, image.getHeight(null) / 2)); }) .enableAsNativeTarget() // required to accept dragging from editor (as editor component doesn't use DnDSupport to implement drag'n'drop) @@ -302,7 +300,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse paintEditorBackgrounds(g, firstVisibleOffset, lastVisibleOffset); Object hint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - if (!UIUtil.isJDKManagedHiDPIScreen(g)) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + if (!UIUtil.isJreHiDPI(this)) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); try { paintAnnotations(g, startVisualLine, endVisualLine); @@ -977,7 +975,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse float scale = myEditor.getScale(); if (Math.abs(1f - scale) > 0.10f) { if (icon instanceof JBUIScaleTrackable) { - ((JBUIScaleTrackable)icon).updateJBUIScale((Graphics2D)GraphicsUtil.safelyGetGraphics(this)); + ((JBUIScaleTrackable)icon).updateJBUIScale(getGraphicsConfiguration()); } return ((ScalableIcon)icon).scale(scale); } @@ -1165,7 +1163,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse int baseHeight, boolean active) { Object antialiasing = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - if (SystemInfo.isMac && SystemInfo.JAVA_VERSION.startsWith("1.4.1") || UIUtil.isJDKManagedHiDPIScreen(g)) { + if (SystemInfo.isMac && SystemInfo.JAVA_VERSION.startsWith("1.4.1") || UIUtil.isJreHiDPI(this)) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ImmediatePainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ImmediatePainter.java index a27f3c658e4d..334d84c83631 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ImmediatePainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ImmediatePainter.java @@ -154,7 +154,7 @@ class ImmediatePainter { //noinspection ConstantConditions final int caretWidth = isBlockCursor ? editor.getCaretLocations(false)[0].myWidth : JBUI.scale(caret.getVisualAttributes().getWidth(settings.getLineCursorWidth())); - final float caretShift = isBlockCursor ? 0 : caretWidth == 1 ? 0 : 1 / JBUI.sysScale((Graphics2D)g); + final float caretShift = isBlockCursor ? 0 : caretWidth == 1 ? 0 : 1 / JBUI.sysScale(myEditor.getComponent()); final Rectangle2D caretRectangle = new Rectangle2D.Float((int)(p2x + width2) - caretShift, p2y - topOverhang, caretWidth, lineHeight + topOverhang + bottomOverhang + (isBlockCursor ? -1 : 0)); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 7fd30e4d8152..3886bc1cbb98 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -836,7 +836,7 @@ class EditorPainter implements TextDrawingCallback { int lineWidth = JBUI.scale(attr.getWidth(settings.getLineCursorWidth())); // fully cover extra character's pixel which can appear due to antialiasing // see IDEA-148843 for more details - if (x > minX && lineWidth > 1) x -= 1 / JBUI.sysScale(g); + if (x > minX && lineWidth > 1) x -= 1 / JBUI.sysScale(myEditor.getComponent()); g.fill(new Rectangle2D.Float(x, y, lineWidth, nominalLineHeight)); if (myDocument.getTextLength() > 0 && caret != null && !myView.getTextLayoutCache().getLineLayout(caret.getLogicalPosition().line).isLtr()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index d91fc0ea5ebf..d065dee27115 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -40,7 +40,6 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; import com.intellij.ui.ScreenUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.messages.MessageBus; -import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -743,7 +742,7 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom int extendedState = updateFrameBounds(frame); - Rectangle rectangle = FrameBoundsConverter.convertToDeviceSpace((Graphics2D)GraphicsUtil.safelyGetGraphics(frame), myFrameBounds); + Rectangle rectangle = FrameBoundsConverter.convertToDeviceSpace(frame.getGraphicsConfiguration(), myFrameBounds); final Element frameElement = new Element(FRAME_ELEMENT); frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x)); @@ -807,8 +806,8 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom } /** - * Converts the frame bounds b/w the user space (JDK-managed HiDPI mode) and the device space (IDE-managed HiDPI mode). - * See {@link UIUtil#isJDKManagedHiDPI()} + * Converts the frame bounds b/w the user space (JRE-managed HiDPI mode) and the device space (IDE-managed HiDPI mode). + * See {@link UIUtil#isJreHiDPIEnabled()} */ private static class FrameBoundsConverter { /** @@ -822,11 +821,11 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom try { for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { Rectangle devBounds = gd.getDefaultConfiguration().getBounds(); // in user space - scaleUp(devBounds, gd); // to device space + scaleUp(devBounds, gd.getDefaultConfiguration()); // to device space Rectangle2D.Float devBounds2D = new Rectangle2D.Float(devBounds.x, devBounds.y, devBounds.width, devBounds.height); Point2D.Float center2d = new Point2D.Float(b.x + b.width / 2, b.y + b.height / 2); if (devBounds2D.contains(center2d)) { - scaleDown(b, gd); + scaleDown(b, gd.getDefaultConfiguration()); break; } } @@ -837,16 +836,16 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom } /** - * @param g the graphics of the device + * @param gc the graphics config * @param bounds the bounds in the user space * @return the bounds in the device space */ - public static Rectangle convertToDeviceSpace(Graphics2D g, @NotNull Rectangle bounds) { + public static Rectangle convertToDeviceSpace(GraphicsConfiguration gc, @NotNull Rectangle bounds) { Rectangle b = bounds.getBounds(); if (!shouldConvert()) return b; try { - scaleUp(b, g.getDeviceConfiguration().getDevice()); + scaleUp(b, gc); } catch (HeadlessException ignore) { } @@ -854,23 +853,23 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom } private static boolean shouldConvert() { - if (SystemInfo.isLinux || // JDK-managed HiDPI mode is not yet implemented (pending) - SystemInfo.isMac) // JDK-managed HiDPI mode is permanent + if (SystemInfo.isLinux || // JRE-managed HiDPI mode is not yet implemented (pending) + SystemInfo.isMac) // JRE-managed HiDPI mode is permanent { return false; } - if (!UIUtil.isJDKManagedHiDPI()) return false; // device space equals user space + if (!UIUtil.isJreHiDPIEnabled()) return false; // device space equals user space return true; } - private static void scaleUp(@NotNull Rectangle bounds, @NotNull GraphicsDevice gd) { - scale(bounds, gd.getDefaultConfiguration().getBounds(), JBUI.sysScale(gd)); + private static void scaleUp(@NotNull Rectangle bounds, @NotNull GraphicsConfiguration gc) { + scale(bounds, gc.getBounds(), JBUI.sysScale(gc)); } - private static void scaleDown(@NotNull Rectangle bounds, @NotNull GraphicsDevice gd) { - float scale = JBUI.sysScale(gd); + private static void scaleDown(@NotNull Rectangle bounds, @NotNull GraphicsConfiguration gc) { + float scale = JBUI.sysScale(gc); assert scale != 0; - scale(bounds, gd.getDefaultConfiguration().getBounds(), 1 / scale); + scale(bounds, gc.getBounds(), 1 / scale); } private static void scale(@NotNull Rectangle bounds, @NotNull Rectangle deviceBounds, float scale) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java index 770c19f67c49..8a507b0ba6d5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java @@ -188,9 +188,9 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget { } UIUtil.drawImage(g, myBufferedImage, 0, 0, null); - if (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)g) && !UIUtil.isUnderDarcula()) { + if (UIUtil.isJreHiDPI(this) && !UIUtil.isUnderDarcula()) { Graphics2D g2 = (Graphics2D)g.create(0, 0, getWidth(), getHeight()); - float s = JBUI.sysScale((Graphics2D)g); + float s = JBUI.sysScale(this); g2.scale(1/s, 1/s); g2.setColor(UIUtil.isUnderIntelliJLaF() ? Gray.xC9 : Gray.x91); g2.drawLine(0, 0, (int)(s * getWidth()), 0); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java index 9be7382319e5..2f5e69c2d8b9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java @@ -83,8 +83,8 @@ public class RecentProjectPanel extends JPanel { private boolean rectInListCoordinatesContains(Rectangle listCellBounds, Point p) { - int realCloseButtonInset = (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)getGraphics())) ? - (int)(closeButtonInset * JBUI.sysScale((Graphics2D)getGraphics())) : closeButtonInset; + int realCloseButtonInset = (UIUtil.isJreHiDPI(this)) ? + (int)(closeButtonInset * JBUI.sysScale(this)) : closeButtonInset; Rectangle closeButtonRect = new Rectangle(myCloseButtonForEditor.getX() - realCloseButtonInset, myCloseButtonForEditor.getY() - realCloseButtonInset, diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 2ca4292100c7..1b40510d70a1 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -1651,8 +1651,9 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { imageGraphics.dispose(); Graphics2D g2d = (Graphics2D)g.create(); try { - if (UIUtil.isJDKManagedHiDPIScreen(g2d)) { - g2d.scale(1/JBUI.sysScale(g2d), 1 / JBUI.sysScale(g2d)); + if (UIUtil.isJreHiDPI(this)) { + float s = 1 / JBUI.sysScale(this); + g2d.scale(s, s); } UIUtil.drawImage(g2d, makeColorTransparent(image, myFillColor), 0, 0, null); } @@ -1716,11 +1717,18 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { private void paintShadow(Graphics graphics) { if (myShadow != null) { - if (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)graphics)) { - graphics = graphics.create(); - ((Graphics2D)graphics).scale(1/JBUI.sysScale((Graphics2D)graphics), 1/JBUI.sysScale((Graphics2D)graphics)); + Graphics2D g2d = (Graphics2D)graphics; + try { + if (UIUtil.isJreHiDPI(this)) { + g2d = (Graphics2D)graphics.create(); + float s = 1 / JBUI.sysScale(this); + g2d.scale(s, s); + } + UIUtil.drawImage(g2d, myShadow.getImage(), myShadow.getX(), myShadow.getY(), null); + } + finally { + if (g2d != graphics) g2d.dispose(); } - UIUtil.drawImage(graphics, myShadow.getImage(), myShadow.getX(), myShadow.getY(), null); } } diff --git a/platform/util/src/com/intellij/openapi/util/IconLoader.java b/platform/util/src/com/intellij/openapi/util/IconLoader.java index fc2ddeded43b..d4ac04b98b1b 100644 --- a/platform/util/src/com/intellij/openapi/util/IconLoader.java +++ b/platform/util/src/com/intellij/openapi/util/IconLoader.java @@ -285,7 +285,7 @@ public final class IconLoader { if (icon instanceof CachedImageIcon) { disabledIcon = ((CachedImageIcon)icon).asDisabledIcon(); } else { - final float scale = UIUtil.isJDKManagedHiDPIScreen() ? JBUI.sysScale() : 1f; // [tav] todo: no screen available + final float scale = UIUtil.isJreHiDPI() ? JBUI.sysScale() : 1f; // [tav] todo: no screen available @SuppressWarnings("UndesirableClassUsage") BufferedImage image = new BufferedImage((int)(scale * icon.getIconWidth()), (int)(scale * icon.getIconHeight()), BufferedImage.TYPE_INT_ARGB); final Graphics2D graphics = image.createGraphics(); @@ -298,7 +298,7 @@ public final class IconLoader { graphics.dispose(); Image img = ImageUtil.filter(image, UIUtil.getGrayFilter()); - if (UIUtil.isJDKManagedHiDPIScreen()) img = RetinaImage.createFrom(img, scale, null); + if (UIUtil.isJreHiDPI()) img = RetinaImage.createFrom(img, scale, null); disabledIcon = new JBImageIcon(img); } @@ -392,9 +392,9 @@ public final class IconLoader { } @Override - public boolean updateJBUIScale(Graphics2D g) { - if (needUpdateJBUIScale(g)) { - getRealIcon(g); // force update + public boolean updateJBUIScale(GraphicsConfiguration gc) { + if (needUpdateJBUIScale(gc)) { + getRealIcon(gc); // force update return true; } return false; @@ -406,12 +406,12 @@ public final class IconLoader { } @NotNull - private synchronized ImageIcon getRealIcon(@Nullable Graphics g) { - if (!isValid() || needUpdateJBUIScale((Graphics2D)g)) { + private synchronized ImageIcon getRealIcon(@Nullable GraphicsConfiguration gc) { + if (!isValid() || needUpdateJBUIScale(gc)) { if (isLoaderDisabled()) return EMPTY_ICON; myRealIcon = null; dark = USE_DARK_ICONS; - super.updateJBUIScale((Graphics2D)g); + super.updateJBUIScale(gc); setGlobalFilter(IMAGE_FILTER); if (!isValid()) myScaledIconsCache.clear(); if (numberOfPatchers != ourPatchers.size()) { @@ -460,7 +460,7 @@ public final class IconLoader { @Override public void paintIcon(Component c, Graphics g, int x, int y) { - getRealIcon(g).paintIcon(c, g, x, y); + getRealIcon(c != null ? c.getGraphicsConfiguration() : null).paintIcon(c, g, x, y); } @Override @@ -543,7 +543,7 @@ public final class IconLoader { Image image = getOrLoadOrigImage(needRetinaImage); if (image == null) return null; - if (!UIUtil.isJDKManagedHiDPI() && needRetinaImage) { + if (!UIUtil.isJreHiDPIEnabled() && needRetinaImage) { instanceScale = effectiveScale / 2f; // the image is 2x raw BufferedImage, compensate it } @@ -576,7 +576,7 @@ public final class IconLoader { @Override public void paintIcon(Component c, Graphics g, int x, int y) { - final Icon icon = getOrComputeIcon((Graphics2D)g); + final Icon icon = getOrComputeIcon(c != null ? c.getGraphicsConfiguration() : null); if (icon != null) { icon.paintIcon(c, g, x, y); } @@ -598,10 +598,10 @@ public final class IconLoader { return getOrComputeIcon(null); } - protected final synchronized Icon getOrComputeIcon(@Nullable Graphics2D g) { - if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || needUpdateJBUIScale(g) || filter != IMAGE_FILTER || numberOfPatchers != ourPatchers.size()) { + protected final synchronized Icon getOrComputeIcon(@Nullable GraphicsConfiguration gc) { + if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || needUpdateJBUIScale(gc) || filter != IMAGE_FILTER || numberOfPatchers != ourPatchers.size()) { isDarkVariant = USE_DARK_ICONS; - updateJBUIScale(g); + updateJBUIScale(gc); filter = IMAGE_FILTER; myWasComputed = true; numberOfPatchers = ourPatchers.size(); diff --git a/platform/util/src/com/intellij/util/ImageLoader.java b/platform/util/src/com/intellij/util/ImageLoader.java index ac7c6ba3cfad..a31c6290b976 100644 --- a/platform/util/src/com/intellij/util/ImageLoader.java +++ b/platform/util/src/com/intellij/util/ImageLoader.java @@ -224,7 +224,7 @@ public class ImageLoader implements Serializable { return with(new ImageConverter() { @Override public Image convert(Image source, ImageDesc desc) { - if (source != null && UIUtil.isJDKManagedHiDPI() && desc.scale > 1) { + if (source != null && UIUtil.isJreHiDPIEnabled() && desc.scale > 1) { return RetinaImage.createFrom(source, (int)desc.scale, ourComponent); } return source; @@ -279,7 +279,7 @@ public class ImageLoader implements Serializable { /** * Loads an image by the passed url in scale (1x, 2x, ...) possibly closed to the passed JBUI pix scale, - * then simply returns it in the JDK-managed HiDPI mode, otherwise scales the image + * then simply returns it in the JRE-managed HiDPI mode, otherwise scales the image * according to the passed scale and returns. */ @Nullable @@ -287,10 +287,10 @@ public class ImageLoader implements Serializable { final float scaleFactor = adjustScaleFactor(allowFloatScaling, pixScale); // valid for Retina as well // We can't check all 3rd party plugins and convince the authors to add @2x icons. - // (scaleFactor > 1.0) != isJDKManagedHiDPI() => we should scale images manually. - // Note we never scale images on JDKManagedHiDPI displays because scaling is handled by the system. + // In IDE-managed HiDPI mode with (scaleFactor > 1.0) we should scale images manually. + // Note we never scale images in JRE-managed HiDPI mode because scaling is handled by JRE. - final boolean scaleImages = (scaleFactor > 1.0f && !UIUtil.isJDKManagedHiDPI()); + final boolean scaleImages = (scaleFactor > 1.0f && !UIUtil.isJreHiDPIEnabled()); // Prefer retina images for HiDPI scale, because downscaling // retina images provides a better result than upscaling non-retina images. diff --git a/platform/util/src/com/intellij/util/JBHiDPIScaledImage.java b/platform/util/src/com/intellij/util/JBHiDPIScaledImage.java index 9feb4d9091b3..a1ee7c05ea53 100644 --- a/platform/util/src/com/intellij/util/JBHiDPIScaledImage.java +++ b/platform/util/src/com/intellij/util/JBHiDPIScaledImage.java @@ -43,11 +43,7 @@ public class JBHiDPIScaledImage extends BufferedImage { * @param type the type */ public JBHiDPIScaledImage(int width, int height, int type) { - super((int)(width * JBUI.sysScale()), (int)(height * JBUI.sysScale()), type); - myImage = null; - myUserWidth = width; - myUserHeight = height; - myScale = JBUI.sysScale(); + this((GraphicsConfiguration)null, width, height, type); } /** @@ -58,12 +54,24 @@ public class JBHiDPIScaledImage extends BufferedImage { * @param height the height in user coordinate space * @param type the type */ - public JBHiDPIScaledImage(@NotNull Graphics2D g, int width, int height, int type) { - super((int)(width * JBUI.sysScale(g)), (int)(height * JBUI.sysScale(g)), type); + public JBHiDPIScaledImage(@Nullable Graphics2D g, int width, int height, int type) { + this(g != null ? g.getDeviceConfiguration() : null, width, height, type); + } + + /** + * Creates a scaled HiDPI-aware BufferedImage, targeting the graphics config. + * + * @param gc the graphics config which provides the target scale + * @param width the width in user coordinate space + * @param height the height in user coordinate space + * @param type the type + */ + public JBHiDPIScaledImage(@Nullable GraphicsConfiguration gc, int width, int height, int type) { + super((int)(width * JBUI.sysScale(gc)), (int)(height * JBUI.sysScale(gc)), type); myImage = null; myUserWidth = width; myUserHeight = height; - myScale = JBUI.sysScale(g); + myScale = JBUI.sysScale(gc); } /** diff --git a/platform/util/src/com/intellij/util/RetinaImage.java b/platform/util/src/com/intellij/util/RetinaImage.java index 6f735a5cd00f..c7604724f4c0 100644 --- a/platform/util/src/com/intellij/util/RetinaImage.java +++ b/platform/util/src/com/intellij/util/RetinaImage.java @@ -83,17 +83,22 @@ public class RetinaImage { // [tav] todo: create HiDPIImage class @NotNull public static BufferedImage create(Graphics2D g, final int width, int height, int type) { - return create(g, null, width, height, type); + return create(g != null ? g.getDeviceConfiguration() : null, null, width, height, type); } @NotNull - private static BufferedImage create(Graphics2D g, Image image, final int width, int height, int type) { + public static BufferedImage create(GraphicsConfiguration gc, final int width, int height, int type) { + return create(gc, null, width, height, type); + } + + @NotNull + private static BufferedImage create(GraphicsConfiguration gc, Image image, final int width, int height, int type) { if (SystemInfo.isAppleJvm) { return AppleHiDPIScaledImage.create(width, height, type); } else { if (image == null) { - return g == null ? new JBHiDPIScaledImage(width, height, type) : - new JBHiDPIScaledImage(g, width, height, type); + return gc == null ? new JBHiDPIScaledImage(width, height, type) : + new JBHiDPIScaledImage(gc, width, height, type); } else { return new JBHiDPIScaledImage(image, width, height, type); } diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 6cc81ecf0db4..26318150125a 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -26,7 +26,6 @@ import com.intellij.util.keyFMap.KeyFMap; import com.intellij.util.ui.components.BorderLayoutPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import sun.awt.image.BufferedImageGraphicsConfig; import javax.swing.*; import javax.swing.border.Border; @@ -53,17 +52,17 @@ public class JBUI { * * 1) IDE-managed HiDPI mode. * - * Supported for backward compatibility until complete transition to the JDK-managed HiDPI mode happens. + * Supported for backward compatibility until complete transition to the JRE-managed HiDPI mode happens. * In this mode there's a single coordinate space and the whole UI is scaled by the IDE guided by the * user scale factor ({@link #USR}). * - * 2) JDK-managed HiDPI mode. + * 2) JRE-managed HiDPI mode. * - * In this mode the JDK scales graphics prior to drawing it on the device. So, there're two coordinate + * In this mode the JRE scales graphics prior to drawing it on the device. So, there're two coordinate * spaces: the user space and the device space. The system scale factor ({@link #SYS}) defines the * transform b/w the spaces. The UI size metrics (windows, controls, fonts height) are in the user * coordinate space. Though, the raster images should be aware of the device scale in order to meet - * HiDPI. (For instance, JDK on a Mac Retina monitor device works in the JDK-managed HiDPI mode, + * HiDPI. (For instance, JRE on a Mac Retina monitor device works in the JRE-managed HiDPI mode, * transforming graphics to the double-scaled device coordinate space) * * The IDE operates the scale factors of the following types: @@ -72,11 +71,14 @@ public class JBUI { * 2) The system (monitor device) scale factor: {@link #SYS} * 3) The pixel scale factor: {@link #PIX} * - * @see UIUtil#isJDKManagedHiDPI() - * @see UIUtil#isJDKManagedHiDPIScreen() - * @see UIUtil#isJDKManagedHiDPIScreen(Graphics2D) + * @see UIUtil#isJreHiDPIEnabled() + * @see UIUtil#isJreHiDPI() + * @see UIUtil#isJreHiDPI(GraphicsConfiguration) + * @see JBUI#isUsrHiDPI() + * @see JBUI#isPixHiDPI(GraphicsConfiguration) * @see UIUtil#drawImage(Graphics, Image, int, int, int, int, ImageObserver) * @see UIUtil#createImage(Graphics, int, int, int) + * @see UIUtil#createImage(GraphicsConfiguration, int, int, int) * @see UIUtil#createImage(int, int, int) */ public enum ScaleType { @@ -86,11 +88,11 @@ public class JBUI { * * The user scale value depends on which HiDPI mode is enabled. In the IDE-managed HiDPI mode the * user scale "includes" the default system scale and simply equals it with the default UI font size. - * In the JDK-managed HiDPI mode the user scale is independent of the system scale and equals 1.0 + * In the JRE-managed HiDPI mode the user scale is independent of the system scale and equals 1.0 * with the default UI font size. In case the default UI font size changes, the user scale changes * proportionally in both the HiDPI modes. * - * In the IDE-managed HiDPI mode the user scale completely defines the UI scale. In the JDK-managed + * In the IDE-managed HiDPI mode the user scale completely defines the UI scale. In the JRE-managed * HiDPI mode the user scale can be considered a supplementary scale taking effect in cases like * the IDE Presentation Mode and when the default UI scale is changed by the user. * @@ -106,28 +108,28 @@ public class JBUI { * there's always a single default system scale factor corresponding to the default device. And it's * the only system scale available in the IDE-managed HiDPI mode. * - * In the JDK-managed HiDPI mode, the system scale defines the scale of the transform b/w the user - * and the device coordinate spaces performed by the JDK. + * In the JRE-managed HiDPI mode, the system scale defines the scale of the transform b/w the user + * and the device coordinate spaces performed by the JRE. * * @see #sysScale() - * @see #sysScale(Graphics2D) - * @see #sysScale(GraphicsDevice) + * @see #sysScale(GraphicsConfiguration) + * @see #sysScale(Component) */ SYS, /** * The pixel scale factor "combines" both the user and the system scale factors and defines the * effective scale of the whole UI. * - * For instance, on Mac Retina monitor (JDK-managed HiDPI) in the Presentation mode (which, say, + * For instance, on Mac Retina monitor (JRE-managed HiDPI) in the Presentation mode (which, say, * doubles the UI scale) the pixel scale would equal 4.0. The value is the product of the user * scale 2.0 and the system scale 2.0. In the IDE-managed HiDPI mode, the pixel scale always equals * the user scale. * * @see #pixScale() - * @see #pixScale(Graphics2D) - * @see #pixScale(GraphicsDevice) + * @see #pixScale(GraphicsConfiguration) + * @see #pixScale(Component) + * @see #pixScale(GraphicsConfiguration, float) * @see #pixScale(float) - * @see #pixScale(Graphics2D, float) */ PIX; @@ -145,7 +147,7 @@ public class JBUI { private static float userScaleFactor; static { - setUserScaleFactor(UIUtil.isJDKManagedHiDPI() ? 1f : SYSTEM_SCALE_FACTOR); + setUserScaleFactor(UIUtil.isJreHiDPIEnabled() ? 1f : SYSTEM_SCALE_FACTOR); } /** @@ -171,13 +173,13 @@ public class JBUI { return SYSTEM_SCALE_FACTOR; } - if (UIUtil.isJDKManagedHiDPI()) { + if (UIUtil.isJreHiDPIEnabled()) { GraphicsDevice gd = null; try { gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); } catch (HeadlessException ignore) {} if (gd != null) { - return sysScale(gd); + return sysScale(gd.getDefaultConfiguration()); } return 1.0f; } @@ -198,38 +200,35 @@ public class JBUI { * In the IDE-managed HiDPI mode defaults to {@link #sysScale()} */ public static float sysScale(JBUIScaleTrackable trackable) { - if (UIUtil.isJDKManagedHiDPI() && trackable != null) { + if (UIUtil.isJreHiDPIEnabled() && trackable != null) { return trackable.getJBUIScale(ScaleType.SYS); } return sysScale(); } /** - * Returns the system scale factor, corresponding to the provided graphics context. + * Returns the system scale factor, corresponding to the graphics configuration * In the IDE-managed HiDPI mode defaults to {@link #sysScale()} */ - public static float sysScale(@Nullable Graphics2D g) { - if (UIUtil.isJDKManagedHiDPI() && g != null) { - GraphicsConfiguration conf = g.getDeviceConfiguration(); - if (conf instanceof BufferedImageGraphicsConfig) { - // take BI's scale directly, not inspecting the device - return (float)g.getTransform().getScaleX(); + public static float sysScale(@Nullable GraphicsConfiguration gc) { + if (UIUtil.isJreHiDPIEnabled() && gc != null) { + if (SystemInfo.isMac && UIUtil.isJreHiDPI_earlierVersion()) { + if (gc.getDevice().getType() == GraphicsDevice.TYPE_RASTER_SCREEN) { + return UIUtil.DetectRetinaKit.isOracleMacRetinaDevice(gc.getDevice()) ? 2f : 1f; + } } - if (conf != null) return sysScale(conf.getDevice()); + return (float)gc.getDefaultTransform().getScaleX(); } return sysScale(); } /** - * Returns the system scale factor, corresponding to the provided device. + * Returns the system scale factor, corresponding to the device the component is tied to. * In the IDE-managed HiDPI mode defaults to {@link #sysScale()} */ - public static float sysScale(@Nullable GraphicsDevice gd) { - if (UIUtil.isJDKManagedHiDPI() && gd != null) { - if (SystemInfo.isMac && UIUtil.isJDKManagedHiDPI_earlierVersion()) { - return UIUtil.DetectRetinaKit.isOracleMacRetinaDevice(gd) ? 2f : 1f; - } - return (float)gd.getDefaultConfiguration().getDefaultTransform().getScaleX(); + public static float sysScale(@Nullable Component comp) { + if (comp != null) { + return sysScale(comp.getGraphicsConfiguration()); } return sysScale(); } @@ -238,7 +237,7 @@ public class JBUI { * Returns the pixel scale factor, corresponding to the default monitor device. */ public static float pixScale() { - return UIUtil.isJDKManagedHiDPI() ? sysScale() * scale(1f) : scale(1f); + return UIUtil.isJreHiDPIEnabled() ? sysScale() * scale(1f) : scale(1f); } /** @@ -249,33 +248,33 @@ public class JBUI { } /** - * Returns "f" scaled by pixScale(g). + * Returns "f" scaled by pixScale(gc). */ - public static float pixScale(@Nullable Graphics2D g, float f) { - return pixScale(g) * f; + public static float pixScale(@Nullable GraphicsConfiguration gc, float f) { + return pixScale(gc) * f; } /** * Returns the pixel scale factor based on the JBUIScaleTrackable. */ public static float pixScale(@NotNull JBUIScaleTrackable trackable) { - return UIUtil.isJDKManagedHiDPI() ? sysScale(trackable) * trackable.getJBUIScale(ScaleType.USR) : trackable.getJBUIScale(ScaleType.USR); + return UIUtil.isJreHiDPIEnabled() ? sysScale(trackable) * trackable.getJBUIScale(ScaleType.USR) : trackable.getJBUIScale(ScaleType.USR); } /** - * Returns the pixel scale factor, corresponding to the provided graphics context. + * Returns the pixel scale factor, corresponding to the provided configuration. * In the IDE-managed HiDPI mode defaults to {@link #pixScale()} */ - public static float pixScale(@Nullable Graphics2D g) { - return g != null ? pixScale(g.getDeviceConfiguration().getDevice()) : pixScale(); + public static float pixScale(@Nullable GraphicsConfiguration gc) { + return UIUtil.isJreHiDPIEnabled() ? sysScale(gc) * scale(1f) : scale(1f); } /** - * Returns the pixel scale factor, corresponding to the provided graphics device. + * Returns the pixel scale factor, corresponding to the device the provided component is tied to. * In the IDE-managed HiDPI mode defaults to {@link #pixScale()} */ - public static float pixScale(@Nullable GraphicsDevice gd) { - return UIUtil.isJDKManagedHiDPI() ? sysScale(gd) * scale(1f) : scale(1f); + public static float pixScale(@Nullable Component comp) { + return pixScale(comp != null ? comp.getGraphicsConfiguration() : null); } private static void setUserScaleFactorProperty(float scale) { @@ -404,78 +403,44 @@ public class JBUI { } /** - * @deprecated use {@link #isHiDPI(Graphics2D, ScaleType)}, {@link #isHiDPI(ScaleType)} + * @deprecated use {@link #isUsrHiDPI()} instead */ @Deprecated public static boolean isHiDPI() { - return isHiDPI(ScaleType.USR); + return isUsrHiDPI(); } /** - * Returns whether the scale factor associated with the graphics context assumes HiDPI-awareness. - * - * @param g the graphics context - * @param type the type of the scale factor - * @return whether HiDPI-awareness is assumed for the scale factor + * Returns whether the {@link ScaleType#USR} scale factor assumes HiDPI-awareness. + * An equivalent of {@code isHiDPI(scale(1f))} */ - public static boolean isHiDPI(@Nullable Graphics2D g, ScaleType type) { - return isHiDPI(g == null ? null : g.getDeviceConfiguration().getDevice(), type); + public static boolean isUsrHiDPI() { + return isHiDPI(scale(1f)); } /** - * Returns whether the scale factor associated with the graphics device assumes HiDPI-awareness. - * - * @param gd the graphics device - * @param type the type of the scale factor - * @return whether HiDPI-awareness is assumed for the scale factor + * Returns whether the {@link ScaleType#PIX} scale factor assumes HiDPI-awareness in the provided graphics config. + * An equivalent of {@code isHiDPI(pixScale(gc))} */ - public static boolean isHiDPI(@Nullable GraphicsDevice gd, ScaleType type) { - switch (type) { - case USR: - return isHiDPI(scale(1f)); - case SYS: - return isHiDPI(sysScale(gd)); - case PIX: - return isHiDPI(pixScale(gd)); - default: - return false; - } + public static boolean isPixHiDPI(@Nullable GraphicsConfiguration gc) { + return isHiDPI(pixScale(gc)); } /** - * Returns whether the scale factor assumes HiDPI-awareness. - * - * @param scale the scale factor - * @return whether HiDPI-awareness is assumed for the scale factor + * Returns whether the {@link ScaleType#PIX} scale factor assumes HiDPI-awareness in the provided component's device. + * An equivalent of {@code isHiDPI(pixScale(comp))} + */ + public static boolean isPixHiDPI(@Nullable Component comp) { + return isHiDPI(pixScale(comp)); + } + + /** + * Returns whether the provided scale assumes HiDPI-awareness. */ public static boolean isHiDPI(float scale) { return scale > 1f; } - /** - * Equivalent of {@link #isHiDPI(Graphics2D, ScaleType)} called for the graphics of the default screen device. - * - * @see #isHiDPI(Graphics2D, ScaleType) - */ - public static boolean isHiDPI(ScaleType type) { - return isHiDPI((GraphicsDevice)null, type); - } - - /** - * Equivalent of {@link #isHiDPI(Graphics2D, ScaleType.USR)} called for the graphics of the specified component. - * - * @see #isHiDPI(Graphics2D, ScaleType) - * @param component if it's {@code null} the graphics of the default screen device will be used - */ - public static boolean isHiDPI(@Nullable Component component) { - Graphics graphics = component != null? component.getGraphics() : null; - try { - return isHiDPI((Graphics2D)graphics, ScaleType.USR); - } finally { - if (graphics != null) graphics.dispose(); - } - } - public static class Fonts { public static JBFont label() { return JBFont.create(UIManager.getFont("Label.font"), false); @@ -578,9 +543,9 @@ public class JBUI { } static float currentJBUIScale() { - // We don't JBUI-scale images in JDK-managed HiDPI mode, see comments in ImageLoader.loadFromUrl(..) + // We don't JBUI-scale images in JRE-managed HiDPI mode, see comments in ImageLoader.loadFromUrl(..) // So, make icons JBUI-scale conformant. - return UIUtil.isJDKManagedHiDPI() ? 1f : scale(1f); + return UIUtil.isJreHiDPIEnabled() ? 1f : scale(1f); } /** @@ -752,12 +717,12 @@ public class JBUI { boolean updateJBUIScale(); /** - * Updates all the scale factors based on the provided graphics (device). + * Updates all the scale factors based on the provided graphics configuration. * - * @param g the graphics, if null defaults to {@link #updateJBUIScale()} + * @param gc the graphics config, if null defaults to {@link #updateJBUIScale()} * @return true if any of the tracked scale factors was updated */ - boolean updateJBUIScale(@Nullable Graphics2D g); + boolean updateJBUIScale(@Nullable GraphicsConfiguration gc); /** * @return true if tracked user scale should be updated @@ -765,10 +730,10 @@ public class JBUI { boolean needUpdateJBUIScale(); /** - * @param g the graphics, if null defaults to {@link #needUpdateJBUIScale()} + * @param gc the graphics config, if null defaults to {@link #needUpdateJBUIScale()} * @return true if any of the tracked scale factors should be updated */ - boolean needUpdateJBUIScale(@Nullable Graphics2D g); + boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc); /** * @param type the type of the scale @@ -809,9 +774,9 @@ public class JBUI { } @Override - public boolean updateJBUIScale(@Nullable Graphics2D g) { + public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) { boolean res = updateJBUIScale(); - if (g != null) res = res || updateJBUIScale(sysScale(g), ScaleType.SYS); + if (gc != null) res = res || updateJBUIScale(sysScale(gc), ScaleType.SYS); return res; } @@ -825,8 +790,8 @@ public class JBUI { } @Override - public boolean needUpdateJBUIScale(@Nullable Graphics2D g) { - return needUpdateJBUIScale() || g != null && needUpdateJBUIScale(sysScale(g), ScaleType.SYS); + public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) { + return needUpdateJBUIScale() || gc != null && needUpdateJBUIScale(sysScale(gc), ScaleType.SYS); } @Override @@ -851,8 +816,8 @@ public class JBUI { } @Override - public boolean updateJBUIScale(@Nullable Graphics2D g) { - return myJBUIScaleDelegate.updateJBUIScale(g); + public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) { + return myJBUIScaleDelegate.updateJBUIScale(gc); } @Override @@ -861,8 +826,8 @@ public class JBUI { } @Override - public boolean needUpdateJBUIScale(@Nullable Graphics2D g) { - return myJBUIScaleDelegate.needUpdateJBUIScale(g); + public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) { + return myJBUIScaleDelegate.needUpdateJBUIScale(gc); } @Override @@ -891,8 +856,8 @@ public class JBUI { } @Override - public boolean updateJBUIScale(@Nullable Graphics2D g) { - return myJBUIScaleDelegate.updateJBUIScale(g); + public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) { + return myJBUIScaleDelegate.updateJBUIScale(gc); } @Override @@ -901,8 +866,8 @@ public class JBUI { } @Override - public boolean needUpdateJBUIScale(@Nullable Graphics2D g) { - return myJBUIScaleDelegate.needUpdateJBUIScale(g); + public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) { + return myJBUIScaleDelegate.needUpdateJBUIScale(gc); } @Override diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 6fa07048419a..780c77a3b9bb 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -339,36 +339,43 @@ public class UIUtil { } /** - * Returns whether the JDK-managed HiDPI mode is enabled and the default monitor device is HiDPI. - * (Equivalent of {@link #isRetina()} on macOS) + * Returns whether the JRE-managed HiDPI mode is enabled and the default monitor device is HiDPI. + * (analogue of {@link #isRetina()} on macOS) */ - public static boolean isJDKManagedHiDPIScreen() { - return isJDKManagedHiDPI() && JBUI.sysScale() > 1.0f; + public static boolean isJreHiDPI() { + return isJreHiDPI((GraphicsConfiguration)null); } /** - * Returns whether the JDK-managed HiDPI mode is enabled and the graphics device is HiDPI. - * (Equivalent of {@link #isRetina(Graphics2D)} on macOS) + * Returns whether the JRE-managed HiDPI mode is enabled and the graphics configuration represents a HiDPI device. + * (analogue of {@link #isRetina(Graphics2D)} on macOS) */ - public static boolean isJDKManagedHiDPIScreen(Graphics2D g) { - return isJDKManagedHiDPI() && JBUI.sysScale(g) > 1.0f; + public static boolean isJreHiDPI(@Nullable GraphicsConfiguration gc) { + return isJreHiDPIEnabled() && JBUI.isHiDPI(JBUI.sysScale(gc)); } - private static Boolean jdkManagedHiDPI; - private static boolean jdkManagedHiDPI_earlierVersion; + /** + * Returns whether the JRE-managed HiDPI mode is enabled and the provided component is tied to a HiDPI device. + */ + public static boolean isJreHiDPI(@Nullable Component comp) { + return isJreHiDPI(comp != null ? comp.getGraphicsConfiguration() : null); + } + + private static Boolean jreHiDPI; + private static boolean jreHiDPI_earlierVersion; /** - * Returns whether the JDK-managed HiDPI mode is enabled. + * Returns whether the JRE-managed HiDPI mode is enabled. * (True for macOS JDK >= 7.10 versions) * * @see JBUI.ScaleType */ - public static boolean isJDKManagedHiDPI() { - if (jdkManagedHiDPI != null) { - return jdkManagedHiDPI; + public static boolean isJreHiDPIEnabled() { + if (jreHiDPI != null) { + return jreHiDPI; } - jdkManagedHiDPI = false; - jdkManagedHiDPI_earlierVersion = true; + jreHiDPI = false; + jreHiDPI_earlierVersion = true; if (SystemInfo.isLinux) { return false; // pending support } @@ -376,25 +383,25 @@ public class UIUtil { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); if (ge instanceof SunGraphicsEnvironment) { Method m = ReflectionUtil.getDeclaredMethod(SunGraphicsEnvironment.class, "isUIScaleOn"); - jdkManagedHiDPI = (Boolean)m.invoke(ge); - jdkManagedHiDPI_earlierVersion = false; + jreHiDPI = (Boolean)m.invoke(ge); + jreHiDPI_earlierVersion = false; } } catch (Throwable ignore) { } if (SystemInfo.isMac) { - return jdkManagedHiDPI = (SystemInfo.isAppleJvm ? false : true); + return jreHiDPI = (SystemInfo.isAppleJvm ? false : true); } - return jdkManagedHiDPI; + return jreHiDPI; } /** * Indicates earlier JBSDK version, not containing HiDPI changes. - * On macOS that JBSDK supports jdkManagedHiDPI, but it's not capable to provide device scale + * On macOS such JBSDK supports jreHiDPI, but it's not capable to provide device scale * via GraphicsDevice transform matrix (the scale should be retrieved via DetectRetinaKit). */ - static boolean isJDKManagedHiDPI_earlierVersion() { - isJDKManagedHiDPI(); - return jdkManagedHiDPI_earlierVersion; + static boolean isJreHiDPI_earlierVersion() { + isJreHiDPIEnabled(); + return jreHiDPI_earlierVersion; } /** @@ -1715,7 +1722,7 @@ public class UIUtil { g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); g.setPaint(getGradientPaint(startXf, 2, c1, startXf, height - 5, c2)); - if (isJDKManagedHiDPIScreen()) { + if (isJreHiDPI(g.getDeviceConfiguration())) { GraphicsConfig c = GraphicsUtil.setupRoundedBorderAntialiasing(g); g.fill(new RoundRectangle2D.Float(startXf, 2, endXf - startXf, height - 4, 5, 5)); c.restore(); @@ -1812,7 +1819,7 @@ public class UIUtil { g.setColor(getPanelBackground()); g.fillRect(x, 0, width, height); - boolean jmHiDPI = isJDKManagedHiDPIScreen((Graphics2D)g); + boolean jmHiDPI = isJreHiDPI(((Graphics2D)g).getDeviceConfiguration()); if (jmHiDPI) { ((Graphics2D)g).setStroke(new BasicStroke(2f)); } @@ -1904,13 +1911,32 @@ public class UIUtil { */ @NotNull public static BufferedImage createImage(int width, int height, int type) { - if (isJDKManagedHiDPIScreen()) { + if (isJreHiDPI()) { return RetinaImage.create(width, height, type); } //noinspection UndesirableClassUsage return new BufferedImage(width, height, type); } + /** + * Creates a HiDPI-aware BufferedImage in the graphics config scale. + * + * @param gc the graphics config + * @param width the width in user coordinate space + * @param height the height in user coordinate space + * @param type the type of the image + * + * @return a HiDPI-aware BufferedImage in the graphics scale + */ + @NotNull + public static BufferedImage createImage(GraphicsConfiguration gc, int width, int height, int type) { + if (isJreHiDPI(gc)) { + return RetinaImage.create(gc, width, height, type); + } + //noinspection UndesirableClassUsage + return new BufferedImage(width, height, type); + } + /** * Creates a HiDPI-aware BufferedImage in the graphics device scale. * @@ -1924,12 +1950,7 @@ public class UIUtil { @NotNull public static BufferedImage createImage(Graphics g, int width, int height, int type) { if (g instanceof Graphics2D) { - Graphics2D g2d = (Graphics2D)g; - if (isJDKManagedHiDPIScreen(g2d)) { - return RetinaImage.create(g2d, width, height, type); - } - //noinspection UndesirableClassUsage - return new BufferedImage(width, height, type); + return createImage(((Graphics2D)g).getDeviceConfiguration(), width, height, type); } return createImage(width, height, type); } @@ -1947,7 +1968,7 @@ public class UIUtil { @NotNull public static BufferedImage createImage(Component comp, int width, int height, int type) { return comp != null ? - createImage(GraphicsUtil.safelyGetGraphics(comp), width, height, type) : + createImage(comp != null ? comp.getGraphicsConfiguration() : null, width, height, type) : createImage(width, height, type); } @@ -2016,7 +2037,7 @@ public class UIUtil { @NotNull Graphics g, boolean useRetinaCondition, Consumer paintRoutine) { - if (!useRetinaCondition || !isJDKManagedHiDPIScreen((Graphics2D)g) || Registry.is("ide.mac.retina.disableDrawingFix")) { + if (!useRetinaCondition || !isJreHiDPI(((Graphics2D)g).getDeviceConfiguration()) || Registry.is("ide.mac.retina.disableDrawingFix")) { paintRoutine.consume((Graphics2D)g); } else { @@ -2167,9 +2188,10 @@ public class UIUtil { public static void drawStringWithHighlighting(Graphics g, String s, int x, int y, Color foreground, Color highlighting) { g.setColor(highlighting); - boolean isRetina = isJDKManagedHiDPIScreen(); - for (float i = x - 1; i <= x + 1; i += isRetina ? 1/JBUI.sysScale() : 1) { - for (float j = y - 1; j <= y + 1; j += isRetina ? 1/JBUI.sysScale() : 1) { + GraphicsConfiguration gc = ((Graphics2D)g).getDeviceConfiguration(); + boolean isRetina = isJreHiDPI(gc); + for (float i = x - 1; i <= x + 1; i += isRetina ? 1/JBUI.sysScale(gc) : 1) { + for (float j = y - 1; j <= y + 1; j += isRetina ? 1/JBUI.sysScale(gc) : 1) { ((Graphics2D)g).drawString(s, i, j); } }