8142966: Wrong cursor position in text components on HiDPI display
Reviewed-by: prr, serb
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java Tue Jul 05 09:26:34 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java Tue Jul 05 09:36:41 2016 +0300
@@ -27,6 +27,7 @@
import java.util.Vector;
import java.util.Properties;
import java.awt.*;
+import java.util.Objects;
import javax.swing.event.*;
/**
@@ -281,7 +282,8 @@
protected void updateMetrics() {
Component host = getContainer();
Font f = host.getFont();
- if (font != f) {
+ FontMetrics fm = (font == null) ? null : host.getFontMetrics(font);
+ if (font != f || !Objects.equals(metrics, fm)) {
// The font changed, we need to recalculate the
// longest line.
calculateLongestLine();
--- a/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java Tue Jul 05 09:26:34 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java Tue Jul 05 09:36:41 2016 +0300
@@ -30,6 +30,7 @@
import static java.awt.RenderingHints.*;
import java.awt.event.*;
import java.awt.font.*;
+import java.awt.geom.AffineTransform;
import java.awt.print.PrinterGraphics;
import java.text.BreakIterator;
import java.text.CharacterIterator;
@@ -1060,17 +1061,23 @@
*/
private static FontRenderContext getFRCProperty(JComponent c) {
if (c != null) {
+
+ GraphicsConfiguration gc = c.getGraphicsConfiguration();
+ AffineTransform tx = (gc == null) ? null : gc.getDefaultTransform();
Object aaHint = c.getClientProperty(KEY_TEXT_ANTIALIASING);
- if (aaHint != null) {
- return getFRCFromCache(aaHint);
- }
+ return getFRCFromCache(tx, aaHint);
}
return null;
}
private static final Object APP_CONTEXT_FRC_CACHE_KEY = new Object();
- private static FontRenderContext getFRCFromCache(Object aaHint) {
+ private static FontRenderContext getFRCFromCache(AffineTransform tx,
+ Object aaHint) {
+ if (tx == null && aaHint == null) {
+ return null;
+ }
+
@SuppressWarnings("unchecked")
Map<Object, FontRenderContext> cache = (Map<Object, FontRenderContext>)
AppContext.getAppContext().get(APP_CONTEXT_FRC_CACHE_KEY);
@@ -1080,15 +1087,45 @@
AppContext.getAppContext().put(APP_CONTEXT_FRC_CACHE_KEY, cache);
}
- FontRenderContext frc = cache.get(aaHint);
+ Object key = (tx == null)
+ ? aaHint
+ : (aaHint == null ? tx : new KeyPair(tx, aaHint));
+
+ FontRenderContext frc = cache.get(key);
if (frc == null) {
- frc = new FontRenderContext(null, aaHint,
- VALUE_FRACTIONALMETRICS_DEFAULT);
- cache.put(aaHint, frc);
+ aaHint = (aaHint == null) ? VALUE_ANTIALIAS_OFF : aaHint;
+ frc = new FontRenderContext(tx, aaHint,
+ VALUE_FRACTIONALMETRICS_DEFAULT);
+ cache.put(key, frc);
}
return frc;
}
+ private static class KeyPair {
+
+ private final Object key1;
+ private final Object key2;
+
+ public KeyPair(Object key1, Object key2) {
+ this.key1 = key1;
+ this.key2 = key2;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof KeyPair)) {
+ return false;
+ }
+ KeyPair that = (KeyPair) obj;
+ return this.key1.equals(that.key1) && this.key2.equals(that.key2);
+ }
+
+ @Override
+ public int hashCode() {
+ return key1.hashCode() + 37 * key2.hashCode();
+ }
+ }
+
/*
* returns true if the Graphics is print Graphics
* false otherwise
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/Utilities/8142966/SwingFontMetricsTest.java Tue Jul 05 09:36:41 2016 +0300
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.awt.Font;
+import java.awt.Graphics;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @bug 8142966
+ * @summary Wrong cursor position in text components on HiDPI display
+ * @run main/othervm -Dsun.java2d.uiScale=2 SwingFontMetricsTest
+ */
+public class SwingFontMetricsTest {
+
+ private static final String LOWER_CASE_TEXT = "the quick brown fox jumps over the lazy dog";
+ private static final String UPPER_CASE_TEXT = LOWER_CASE_TEXT.toUpperCase();
+ private static final String TEXT = LOWER_CASE_TEXT + UPPER_CASE_TEXT;
+ private static boolean passed = false;
+ private static CountDownLatch latch = new CountDownLatch(1);
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(SwingFontMetricsTest::createAndShowGUI);
+ latch.await(5, TimeUnit.SECONDS);
+
+ if (!passed) {
+ throw new RuntimeException("Test Failed!");
+ }
+ }
+
+ private static void createAndShowGUI() {
+ final JFrame frame = new JFrame();
+ frame.setSize(300, 300);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ JLabel label = new JLabel(TEXT) {
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ Font font = getFont();
+ int width1 = getFontMetrics(font).stringWidth(TEXT);
+ int width2 = g.getFontMetrics(font).stringWidth(TEXT);
+ passed = (width1 == width2);
+ latch.countDown();
+ frame.dispose();
+ }
+ };
+ frame.add(label);
+ frame.setVisible(true);
+ }
+}