[jdk20] RFR: 4512626: Non-editable JTextArea provides no visual indication of keyboard focus [v2]

Alexander Zvegintsev azvegint at openjdk.org
Fri Dec 16 01:33:06 UTC 2022


On Thu, 15 Dec 2022 07:29:32 GMT, Alexander Zuev <kizune at openjdk.org> wrote:

>> Set the text caret to be visible but not blinking on the non-editable text area. Fix the regression test that becames unstable after the change.
>
> Alexander Zuev has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Fixed MultiSelectionText so it is now stable on Linux
>   Removed both fixed tests from ProblemList

src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java line 389:

> 387:             } else {
> 388:                 if (getBlinkRate() != 0) {
> 389:                     savedBlinkRate = getBlinkRate();

Look like this can override blink rate set by user:


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Robot;
import java.lang.reflect.InvocationTargetException;

public class CaretThing {

    static JFrame frame;
    static JTextField textField;
    static Robot robot;
    static JButton button;

    static void printBlinkRate() {
        System.err.println("Caret blink rate: " + textField.getCaret().getBlinkRate());
    }

    static void requestFocus(Component component) throws InterruptedException, InvocationTargetException {
        robot.waitForIdle();
        robot.delay(300);

        SwingUtilities.invokeAndWait(() -> {
            System.err.println("Requesting focus on " + component);
            printBlinkRate();
            component.requestFocus();
            printBlinkRate();
        });
    }

    static void changeEditable() throws InterruptedException, InvocationTargetException {
        robot.waitForIdle();
        robot.delay(300);
        SwingUtilities.invokeAndWait(()-> {
            System.err.println("Changing editable");
            printBlinkRate();
            textField.setEditable(!textField.isEditable());
            printBlinkRate();
        });
    }

    public static void main(String[] args) throws Exception {
        robot = new Robot();
        robot.setAutoWaitForIdle(true);
        robot.setAutoDelay(50);

        SwingUtilities.invokeAndWait(() -> {
            frame = new JFrame("Hey");
            frame.setLocationRelativeTo(null);
            textField = new JTextField("Some long field value");

            textField.setEditable(false);
            frame.setLayout(new BorderLayout());
            frame.add(textField, BorderLayout.NORTH);

            button = new JButton("Button");
            button.addActionListener((e)-> printBlinkRate());

            frame.add(button, BorderLayout.CENTER);
            frame.pack();
            frame.setVisible(true);

            button.requestFocus();
            textField.getCaret().setBlinkRate(2500);
        });

        requestFocus(textField);

        requestFocus(button); // comment this to get 0 blink rate on editable field

        changeEditable();

        requestFocus(textField);

        SwingUtilities.invokeAndWait(CaretThing::printBlinkRate);
    }
}

Running the sample above at least two possible misbehaviors(tested on Linux):
* you will receive blink rate `500` instead of user set `2500`
* but if you comment `requestFocus(button);` line then blink rate will be `0` (it shows non-blinking cursor)

<hr>

Other than that I am worried about `getBlinkRate()` does not return the same value as passed to`setBlinkRate()` (e.g. case when component is not editable, possible JCK issue?)

src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java line 1050:

> 1048:                     flasher = new Timer(rate, handler);
> 1049:                 }
> 1050:                 flasher.setDelay(rate);

Coming back to negative rate, looks like this changes the previous behavior:

Before the fix it did throw IAE in all cases:

https://github.com/openjdk/jdk20/blob/ca39eb906692568347e7f264520593188f9276cf/src/java.desktop/share/classes/javax/swing/Timer.java#L397-L406

After the fix IAE is thrown only if component is editable<br>
In case of non-editable and may throw it way later after `setEditable(true)` call and focus gain.

-------------

PR: https://git.openjdk.org/jdk20/pull/21



More information about the client-libs-dev mailing list