From fcfc61cf24a4065b1cc6286efcacd85a428740f1 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 1 Mar 2018 18:22:25 +0300 Subject: [PATCH] Fix "hidpi" property - When disabled, it should suppress JRE-HiDPI mode - New test - New run config for a standalone (fork) test run mode --- .../src/com/intellij/idea/StartupUtil.java | 11 ++++ .../com/intellij/util/IconsLoadTimeTest.java | 12 ++--- .../com/intellij/util/ui/HidpiPropTest.java | 49 +++++++++++++++++ .../com/intellij/util/ui/TestScaleHelper.java | 44 ++++++++++++++- .../util/src/com/intellij/util/ui/UIUtil.java | 53 +++++++++++-------- 5 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/util/ui/HidpiPropTest.java diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index 2ebfad1c5d13..1da9be64cc97 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -27,6 +27,7 @@ import com.intellij.ui.AppUIUtil; import com.intellij.util.Consumer; import com.intellij.util.EnvironmentUtil; import com.intellij.util.PlatformUtils; +import com.intellij.util.SystemProperties; import com.intellij.util.ui.UIUtil; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; @@ -82,6 +83,8 @@ public class StartupUtil { IdeaForkJoinWorkerThreadFactory.setupForkJoinCommonPool(Main.isHeadless(args)); boolean newConfigFolder = false; + checkHiDPISettings(); + if (!Main.isHeadless()) { AppUIUtil.updateFrameClass(); newConfigFolder = !new File(PathManager.getConfigPath()).exists(); @@ -180,6 +183,14 @@ public class StartupUtil { return true; } + // called via reflection from com.intellij.util.ui.HidpiPropTest + private static void checkHiDPISettings() { + if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + // suppress JRE-HiDPI mode + System.setProperty("sun.java2d.uiScale.enabled", "false"); + } + } + private static synchronized boolean checkSystemFolders() { String configPath = PathManager.getConfigPath(); PathManager.ensureConfigFolderExists(); diff --git a/platform/platform-tests/testSrc/com/intellij/util/IconsLoadTimeTest.java b/platform/platform-tests/testSrc/com/intellij/util/IconsLoadTimeTest.java index 8715475fc4d0..b9f74fada575 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/IconsLoadTimeTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/IconsLoadTimeTest.java @@ -8,6 +8,7 @@ import com.intellij.internal.IconsLoadTime.StatData; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ui.TestScaleHelper; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -32,13 +33,11 @@ public class IconsLoadTimeTest { // a list of icons for which we have SVG versions private static final String ICONS_LIST_PATH = PlatformTestUtil.getPlatformTestDataPath() + "icons/icons_list.txt"; - private static String initialInternalProp; private static boolean initialSvgProp; @Before public void setState() { - initialInternalProp = System.getProperty("idea.is.internal"); - System.setProperty("idea.is.internal", "true"); + TestScaleHelper.setProperty("idea.is.internal", "true"); RegistryValue rv = Registry.get("ide.svg.icon"); initialSvgProp = rv.asBoolean(); rv.setValue(true); @@ -68,12 +67,7 @@ public class IconsLoadTimeTest { @After public void restoreState() { - if (initialInternalProp == null) { - System.clearProperty("idea.is.internal"); - } - else { - System.setProperty("idea.is.internal", initialInternalProp); - } + TestScaleHelper.restoreProperties(); Registry.get("ide.svg.icon").setValue(initialSvgProp); } } diff --git a/platform/platform-tests/testSrc/com/intellij/util/ui/HidpiPropTest.java b/platform/platform-tests/testSrc/com/intellij/util/ui/HidpiPropTest.java new file mode 100644 index 000000000000..8ad5af29813d --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/util/ui/HidpiPropTest.java @@ -0,0 +1,49 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.util.ui; + +import com.intellij.idea.StartupUtil; +import com.intellij.util.MethodInvocator; +import com.intellij.util.ReflectionUtil; +import com.intellij.util.SystemProperties; +import org.junit.*; + +import javax.swing.*; +import java.awt.*; + +/** + * Tests "hidpi" system property. + * + * @author tav + */ +public class HidpiPropTest { + static final String HIDPI_PROP = "hidpi"; + static final String UI_SCALE_PROP = "sun.java2d.uiScale.enabled"; + static final String STANDALONE_PROP = "intellij.test.standalone"; + + @Before + public void checkStandalone() { + Assume.assumeTrue("not in " + STANDALONE_PROP + " mode", SystemProperties.is(STANDALONE_PROP)); + } + + @Before + public void setState() { + TestScaleHelper.setProperty(HIDPI_PROP, "false"); + MethodInvocator m = new MethodInvocator(StartupUtil.class, "checkHiDPISettings"); + Assume.assumeTrue("StartupUtil.checkHiDPISettings method not available", m.isAvailable()); + m.invoke(null); + } + + @After + public void restoreState() { + TestScaleHelper.restoreProperties(); + } + + @Test + public void test() { + Graphics2D g = TestScaleHelper.createGraphics(2); + + Assert.assertFalse(UI_SCALE_PROP + " should be disabled", SystemProperties.is(UI_SCALE_PROP)); + Assert.assertFalse("hidpi should be disabled", UIUtil.isJreHiDPI()); + Assert.assertFalse("hidpi should be disabled", UIUtil.isJreHiDPI(g)); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/util/ui/TestScaleHelper.java b/platform/platform-tests/testSrc/com/intellij/util/ui/TestScaleHelper.java index 25170de0a777..d4bc6c87d26d 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/ui/TestScaleHelper.java +++ b/platform/platform-tests/testSrc/com/intellij/util/ui/TestScaleHelper.java @@ -2,14 +2,26 @@ package com.intellij.util.ui; import com.intellij.util.FieldAccessor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.After; import org.junit.Before; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + /** * @author tav */ +@SuppressWarnings("JUnitTestCaseWithNoTests") public class TestScaleHelper { - private static final FieldAccessor JRE_HIDPI_ACCESSOR = new FieldAccessor<>(UIUtil.class, "jreHiDPI"); + private static final FieldAccessor> JRE_HIDPI_ACCESSOR = + new FieldAccessor<>(UIUtil.class, "jreHiDPI"); + + private static final Map origProps = new HashMap<>(); private float originalUserScale; private boolean originalJreHiDPIEnabled; @@ -24,9 +36,37 @@ public class TestScaleHelper { public void restoreState() { JBUI.setUserScaleFactor(originalUserScale); overrideJreHiDPIEnabled(originalJreHiDPIEnabled); + restoreProperties(); + } + + public static void setProperty(@NotNull String name, @Nullable String value) { + origProps.put(name, System.getProperty(name)); + _setProperty(name, value); + } + + private static void _setProperty(String name, String value) { + if (value != null) { + System.setProperty(name, value); + } + else { + System.clearProperty(name); + } + } + + public static void restoreProperties() { + for (Map.Entry entry : origProps.entrySet()) { + _setProperty(entry.getKey(), entry.getValue()); + } } public static void overrideJreHiDPIEnabled(boolean enabled) { - JRE_HIDPI_ACCESSOR.set(null, enabled); + JRE_HIDPI_ACCESSOR.get(null).set(enabled); + } + + public static Graphics2D createGraphics(double scale) { + //noinspection UndesirableClassUsage + Graphics2D g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics(); + g.scale(scale, scale); + return g; } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 9663c30a04af..68f55292f908 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -78,6 +78,7 @@ import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; /** @@ -387,9 +388,9 @@ public class UIUtil { return isJreHiDPIEnabled() && JBUI.isHiDPI(JBUI.sysScale(ctx)); } - // accessed from com.intellij.util.ui.paint.AbstractPainter2D via reflect - private static Boolean jreHiDPI; - private static boolean jreHiDPI_earlierVersion; + // accessed from com.intellij.util.ui.TestScaleHelper via reflect + private static final AtomicReference jreHiDPI = new AtomicReference(); + private static volatile boolean jreHiDPI_earlierVersion; /** * Returns whether the JRE-managed HiDPI mode is enabled. @@ -398,30 +399,36 @@ public class UIUtil { * @see JBUI.ScaleType */ public static boolean isJreHiDPIEnabled() { - if (jreHiDPI != null) { - return jreHiDPI; - } - jreHiDPI = false; - jreHiDPI_earlierVersion = true; - if (SystemInfo.isLinux) { - return false; // pending support - } - if (SystemInfo.isJetBrainsJvm) { - try { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - if (ge instanceof SunGraphicsEnvironment) { - Method m = ReflectionUtil.getDeclaredMethod(SunGraphicsEnvironment.class, "isUIScaleOn"); - jreHiDPI = (Boolean)m.invoke(ge); - jreHiDPI_earlierVersion = false; + if (jreHiDPI.get() != null) return jreHiDPI.get(); + + synchronized (jreHiDPI) { + if (jreHiDPI.get() != null) return jreHiDPI.get(); + + jreHiDPI.set(false); + if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + return false; + } + jreHiDPI_earlierVersion = true; + if (SystemInfo.isLinux) { + return false; // pending support + } + if (SystemInfo.isJetBrainsJvm) { + try { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (ge instanceof SunGraphicsEnvironment) { + Method m = ReflectionUtil.getDeclaredMethod(SunGraphicsEnvironment.class, "isUIScaleOn"); + jreHiDPI.set(m != null && (Boolean)m.invoke(ge)); + jreHiDPI_earlierVersion = false; + } + } + catch (Throwable ignore) { } } - catch (Throwable ignore) { + if (SystemInfo.isMac) { + jreHiDPI.set(true); } + return jreHiDPI.get(); } - if (SystemInfo.isMac) { - jreHiDPI = true; - } - return jreHiDPI; } /**