-
Bug
-
Resolution: Unresolved
-
P3
-
9, 11, 17, 21, 22, 23
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
If the text in a JTextComponent contains a character with multiple combining diacritical marks, this prevents correct caret positioning. Navigation of the caret with the left and right arrow keys breaks when such character is encountered, e.g. the caret jumps to the end of the text when navigating from left to right. Positioning of the caret with a mouse click also doesn't work in such case. This makes it impossible to select or edit part of the text.
REGRESSION : Last worked in version 8u401
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Add a JTextField to a JFrame, with the following text,
\u0063\u0064\u0065\u0301\u0020\u0063\u0062\u0061\u0328\u0304\u0301\u0020\u0067\u0068\u0069\u0304\u002e
place the caret before the first character and use the RIGHT arrow to navigate the caret to the right until it jumps to the end.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
On every keystroke the caret is expected to move one position in the text.
ACTUAL -
When the caret is just before the character with more than one combining diacritical mark, the next right arrow keystroke causes the caret to jump to the end of the text instead of moving one position forward.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.JTextComponent;
/**
* A class to demonstrate incorrect caret navigation in text components
* containing characters with multiple combining diacritical marks.
*/
public class CaretTest {
public static void main(final String[] argum) {
System.out.println("Java version: " + System.getProperty("java.version"));
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
createFrame();
}
});
} catch (InterruptedException | InvocationTargetException e) {
e.printStackTrace();
}
}
public static void createFrame() {
JFrame frame = new JFrame("Caret - diacritical marks test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
String testText = "\u0063\u0064\u0065\u0301\u0020\u0063\u0062\u0061\u0328\u0304\u0301\u0020\u0067\u0068\u0069\u0304\u002e";
JTextField textField = new JTextField(testText);
JTextArea textArea = new JTextArea(testText);
frame.getContentPane().add(textField, BorderLayout.PAGE_START);
frame.getContentPane().add(textArea, BorderLayout.CENTER);
Border border = new CompoundBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5), textField.getBorder());
textField.setBorder(border);
textArea.setBorder(border);
frame.setSize(400, 200);
frame.setVisible(true);
// start a Robot to move the caret forward and backward with right and left arrow keys
// the error condition: the caret position sequence is 0,1,2,3,4,5,6,7,17 and back again
new Thread(new Runnable() {
public void run() {
try {
textField.setCaretPosition(0);
JTextComponent focusComponent = textField;
int event = KeyEvent.VK_RIGHT;
Robot robot = new Robot();
robot.setAutoDelay(500);
robot.waitForIdle();
// to show the effect with shift key, selecting part of the text
// robot.keyPress(KeyEvent.VK_SHIFT);
// loop until the frame is closed
while (true) {
System.out.println(focusComponent.getCaretPosition() + " of " + testText.length());
robot.keyPress(event);
if (focusComponent.getCaretPosition() == testText.length()) {
event = KeyEvent.VK_LEFT;
} else if (focusComponent.getCaretPosition() == 0) {
// transfer the focus to the other component
focusComponent = focusComponent == textField ? textArea : textField;
focusComponent.requestFocus();
event = KeyEvent.VK_RIGHT;
robot.delay(500);
}
}
} catch (AWTException ae) {
ae.printStackTrace();
}
}
}).start();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Haven't found one.
Not sure if this is relevant, but in the array of 'valid' characters named 'charIndices' (e.g. in StandardGlyphVector in caretAtOffsetIsValid() in ExtendedTextSourceLabel), the indices of single combining diacritical marks are left out, but of a sequence of combining diacritical marks only the index of the first one is left out.
FREQUENCY : always
If the text in a JTextComponent contains a character with multiple combining diacritical marks, this prevents correct caret positioning. Navigation of the caret with the left and right arrow keys breaks when such character is encountered, e.g. the caret jumps to the end of the text when navigating from left to right. Positioning of the caret with a mouse click also doesn't work in such case. This makes it impossible to select or edit part of the text.
REGRESSION : Last worked in version 8u401
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Add a JTextField to a JFrame, with the following text,
\u0063\u0064\u0065\u0301\u0020\u0063\u0062\u0061\u0328\u0304\u0301\u0020\u0067\u0068\u0069\u0304\u002e
place the caret before the first character and use the RIGHT arrow to navigate the caret to the right until it jumps to the end.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
On every keystroke the caret is expected to move one position in the text.
ACTUAL -
When the caret is just before the character with more than one combining diacritical mark, the next right arrow keystroke causes the caret to jump to the end of the text instead of moving one position forward.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.JTextComponent;
/**
* A class to demonstrate incorrect caret navigation in text components
* containing characters with multiple combining diacritical marks.
*/
public class CaretTest {
public static void main(final String[] argum) {
System.out.println("Java version: " + System.getProperty("java.version"));
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
createFrame();
}
});
} catch (InterruptedException | InvocationTargetException e) {
e.printStackTrace();
}
}
public static void createFrame() {
JFrame frame = new JFrame("Caret - diacritical marks test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
String testText = "\u0063\u0064\u0065\u0301\u0020\u0063\u0062\u0061\u0328\u0304\u0301\u0020\u0067\u0068\u0069\u0304\u002e";
JTextField textField = new JTextField(testText);
JTextArea textArea = new JTextArea(testText);
frame.getContentPane().add(textField, BorderLayout.PAGE_START);
frame.getContentPane().add(textArea, BorderLayout.CENTER);
Border border = new CompoundBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5), textField.getBorder());
textField.setBorder(border);
textArea.setBorder(border);
frame.setSize(400, 200);
frame.setVisible(true);
// start a Robot to move the caret forward and backward with right and left arrow keys
// the error condition: the caret position sequence is 0,1,2,3,4,5,6,7,17 and back again
new Thread(new Runnable() {
public void run() {
try {
textField.setCaretPosition(0);
JTextComponent focusComponent = textField;
int event = KeyEvent.VK_RIGHT;
Robot robot = new Robot();
robot.setAutoDelay(500);
robot.waitForIdle();
// to show the effect with shift key, selecting part of the text
// robot.keyPress(KeyEvent.VK_SHIFT);
// loop until the frame is closed
while (true) {
System.out.println(focusComponent.getCaretPosition() + " of " + testText.length());
robot.keyPress(event);
if (focusComponent.getCaretPosition() == testText.length()) {
event = KeyEvent.VK_LEFT;
} else if (focusComponent.getCaretPosition() == 0) {
// transfer the focus to the other component
focusComponent = focusComponent == textField ? textArea : textField;
focusComponent.requestFocus();
event = KeyEvent.VK_RIGHT;
robot.delay(500);
}
}
} catch (AWTException ae) {
ae.printStackTrace();
}
}
}).start();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Haven't found one.
Not sure if this is relevant, but in the array of 'valid' characters named 'charIndices' (e.g. in StandardGlyphVector in caretAtOffsetIsValid() in ExtendedTextSourceLabel), the indices of single combining diacritical marks are left out, but of a sequence of combining diacritical marks only the index of the first one is left out.
FREQUENCY : always