Bug
- Resolution: Fixed
P3
- 9, 10, 11, 12, 13
- b23
- x86_64
- windows_10
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8267054 | 11.0.13-oracle | Rajat Mahajan | P3 | Resolved | Fixed | b02 |
JDK-8271541 | 11.0.13 | Martin Doerr | P3 | Resolved | Fixed | b01 |
ADDITIONAL SYSTEM INFORMATION :
Windows 10, JDK 13
A DESCRIPTION OF THE PROBLEM :
JTextPane still has the issue with caret position described here: https://bugs.openjdk.java.net/browse/JDK-8199441
JTextArea works well in JDK > 11.0.1, whereas JTextPane does not.
REGRESSION : Last worked in version 8u221
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Run Windows
2) Set the screen resolution to 150%
3) Start the provided Java program
4) It shows a JTextPane pre-filled with text
5) Click at random places in the text and the caret is inserted find at the cursor position
6) Now check "Line Wrap" and repeat the previous step and you will see that the caret is not positioned at the cursor position
Further, the demo program shows a combobox with all available fonts. Almost all of them gives the same result, except for example the Monospaced font. It works fine with it even with Line Wrap checked.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The caret should always be inserted where the mouse is clicked.
ACTUAL -
The caret is not in the same position as where the cursor is clicked.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
/**
* Test to show that the caret when left-click doesn't align with
* the mouse pointer position on Windows with Java 13 and screen resolution > 100%.
*/
public class TestCaretJava13 {
private TestCaretJava13() {
JFrame f = new JFrame("Test Cursor/Caret with Java 9");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JTextPane textPane = new JTextPane();
JComboBox<Font> fontCombo = new JComboBox<>();
fontCombo.setMaximumRowCount(20);
fontCombo.addItemListener(e -> {
Font font = (Font) e.getItem();
textPane.setFont(font);
});
fontCombo.addItem(textPane.getFont());
fontCombo.addItem(new Font("Monospaced", Font.PLAIN, 12));
List<Font> fonts = getFonts();
for (Font font : fonts) {
fontCombo.addItem(font);
}
fillTextPane(textPane);
JPanel toolbar = new JPanel();
toolbar.add(fontCombo);
f.add(toolbar, BorderLayout.NORTH);
f.add(new JScrollPane(textPane), BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
private void fillTextPane(JTextPane textPane) {
StringBuilder buf = new StringBuilder();
addSystemProperties(buf);
for (int i = 0; i < 30; i++) {
StringBuilder row = new StringBuilder();
for (int j = 0; j < 50; j++) {
row.append(j);
if (j % 5 == 0) {
row.append(" ");
}
}
buf.append(row).append(System.lineSeparator());
}
textPane.setText(buf.toString());
textPane.setCaretPosition(0);
}
private void addSystemProperties(StringBuilder buf) {
buf.append("os.name: ").append(System.getProperty("os.name")).append(System.lineSeparator());
buf.append("os.version: ").append(System.getProperty("os.version")).append(System.lineSeparator());
buf.append("os.arch: ").append(System.getProperty("os.arch")).append(System.lineSeparator());
buf.append("java.version: ").append(System.getProperty("java.version")).append(System.lineSeparator());
buf.append("java.vm.name: ").append(System.getProperty("java.vm.name")).append(System.lineSeparator());
buf.append("java.vm.vendor: ").append(System.getProperty("java.vm.vendor")).append(System.lineSeparator());
buf.append("java.home: ").append(System.getProperty("java.home")).append(System.lineSeparator());
buf.append("Monitors: ").append(System.lineSeparator()).append(getScreenInfo()).append(System.lineSeparator());
buf.append(System.lineSeparator());
}
private static String getScreenInfo() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devices = env.getScreenDevices();
StringBuilder returnString = new StringBuilder();
int screenNo = 1;
for (GraphicsDevice device : devices) {
DisplayMode displayMode = device.getDisplayMode();
if (returnString.length() > 0) {
returnString.append(System.lineSeparator());
}
returnString.append("Screen ").append(screenNo++);
returnString.append(": size: ").append(displayMode.getWidth()).append(" x ").append(displayMode.getHeight());
returnString.append(", refresh rate: ").append(displayMode.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN ? displayMode.getRefreshRate() : "unknown");
returnString.append(", bit depth: ").append(displayMode.getBitDepth());
if (isHiDPI(device)) {
returnString.append(", HiDPI display: true");
}
}
return returnString.toString();
}
private static boolean isHiDPI(GraphicsDevice device) {
try {
Field field = device.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(device);
if (scale instanceof Integer && (Integer) scale == 2) {
return true;
}
}
} catch (Throwable ignore) {
}
return device.getDefaultConfiguration().getDefaultTransform().getScaleX() == 2;
}
private List<Font> getFonts() {
List<Font> fonts = new ArrayList<>();
String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String fontFamilyName : fontFamilyNames) {
Font font = new Font(fontFamilyName, Font.PLAIN, 12);
fonts.add(font);
}
return fonts;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestCaretJava13::new);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Either set resolution in Windows to 100% or use the Monospaced font in Java
FREQUENCY : always
Windows 10, JDK 13
A DESCRIPTION OF THE PROBLEM :
JTextPane still has the issue with caret position described here: https://bugs.openjdk.java.net/browse/JDK-8199441
JTextArea works well in JDK > 11.0.1, whereas JTextPane does not.
REGRESSION : Last worked in version 8u221
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Run Windows
2) Set the screen resolution to 150%
3) Start the provided Java program
4) It shows a JTextPane pre-filled with text
5) Click at random places in the text and the caret is inserted find at the cursor position
6) Now check "Line Wrap" and repeat the previous step and you will see that the caret is not positioned at the cursor position
Further, the demo program shows a combobox with all available fonts. Almost all of them gives the same result, except for example the Monospaced font. It works fine with it even with Line Wrap checked.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The caret should always be inserted where the mouse is clicked.
ACTUAL -
The caret is not in the same position as where the cursor is clicked.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
/**
* Test to show that the caret when left-click doesn't align with
* the mouse pointer position on Windows with Java 13 and screen resolution > 100%.
*/
public class TestCaretJava13 {
private TestCaretJava13() {
JFrame f = new JFrame("Test Cursor/Caret with Java 9");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JTextPane textPane = new JTextPane();
JComboBox<Font> fontCombo = new JComboBox<>();
fontCombo.setMaximumRowCount(20);
fontCombo.addItemListener(e -> {
Font font = (Font) e.getItem();
textPane.setFont(font);
});
fontCombo.addItem(textPane.getFont());
fontCombo.addItem(new Font("Monospaced", Font.PLAIN, 12));
List<Font> fonts = getFonts();
for (Font font : fonts) {
fontCombo.addItem(font);
}
fillTextPane(textPane);
JPanel toolbar = new JPanel();
toolbar.add(fontCombo);
f.add(toolbar, BorderLayout.NORTH);
f.add(new JScrollPane(textPane), BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
private void fillTextPane(JTextPane textPane) {
StringBuilder buf = new StringBuilder();
addSystemProperties(buf);
for (int i = 0; i < 30; i++) {
StringBuilder row = new StringBuilder();
for (int j = 0; j < 50; j++) {
row.append(j);
if (j % 5 == 0) {
row.append(" ");
}
}
buf.append(row).append(System.lineSeparator());
}
textPane.setText(buf.toString());
textPane.setCaretPosition(0);
}
private void addSystemProperties(StringBuilder buf) {
buf.append("os.name: ").append(System.getProperty("os.name")).append(System.lineSeparator());
buf.append("os.version: ").append(System.getProperty("os.version")).append(System.lineSeparator());
buf.append("os.arch: ").append(System.getProperty("os.arch")).append(System.lineSeparator());
buf.append("java.version: ").append(System.getProperty("java.version")).append(System.lineSeparator());
buf.append("java.vm.name: ").append(System.getProperty("java.vm.name")).append(System.lineSeparator());
buf.append("java.vm.vendor: ").append(System.getProperty("java.vm.vendor")).append(System.lineSeparator());
buf.append("java.home: ").append(System.getProperty("java.home")).append(System.lineSeparator());
buf.append("Monitors: ").append(System.lineSeparator()).append(getScreenInfo()).append(System.lineSeparator());
buf.append(System.lineSeparator());
}
private static String getScreenInfo() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devices = env.getScreenDevices();
StringBuilder returnString = new StringBuilder();
int screenNo = 1;
for (GraphicsDevice device : devices) {
DisplayMode displayMode = device.getDisplayMode();
if (returnString.length() > 0) {
returnString.append(System.lineSeparator());
}
returnString.append("Screen ").append(screenNo++);
returnString.append(": size: ").append(displayMode.getWidth()).append(" x ").append(displayMode.getHeight());
returnString.append(", refresh rate: ").append(displayMode.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN ? displayMode.getRefreshRate() : "unknown");
returnString.append(", bit depth: ").append(displayMode.getBitDepth());
if (isHiDPI(device)) {
returnString.append(", HiDPI display: true");
}
}
return returnString.toString();
}
private static boolean isHiDPI(GraphicsDevice device) {
try {
Field field = device.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(device);
if (scale instanceof Integer && (Integer) scale == 2) {
return true;
}
}
} catch (Throwable ignore) {
}
return device.getDefaultConfiguration().getDefaultTransform().getScaleX() == 2;
}
private List<Font> getFonts() {
List<Font> fonts = new ArrayList<>();
String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String fontFamilyName : fontFamilyNames) {
Font font = new Font(fontFamilyName, Font.PLAIN, 12);
fonts.add(font);
}
return fonts;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestCaretJava13::new);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Either set resolution in Windows to 100% or use the Monospaced font in Java
FREQUENCY : always
- backported by
JDK-8267054Wrong caret position in JTextPane on Windows with a screen resolution > 100%
- Resolved
JDK-8271541Wrong caret position in JTextPane on Windows with a screen resolution > 100%
- Resolved
- relates to
JDK-8199441Wrong caret position in multiline text components on Windows with a screen resolution higher than 100%
- Resolved
JDK-8254085javax/swing/text/Caret/TestCaretPositionJTextPane.java failed with "RuntimeException: Wrong caret position"
- Resolved
JDK-8186558javax.swing.text.Utilities.getTabbedTextOffset returns incorrect value at end of text when fractional metrics are enabled
- Closed
(2 links to)