On Thu, 27 Jun 2024 10:06:49 GMT, Abhishek Kumar <abhis...@openjdk.org> wrote:

>> In GTK LAF, the menu mnemonics are always displayed which is different from 
>> the native behavior. In native application **(tested with gedit for normal 
>> buttons and tested with libreoffice for menu**), the menu mnemonics toggle 
>> on press of `ALT` key. Menu mnemonics are hidden initially and then toggles 
>> between show/hide on `ALT` press. 
>> Proposed fix is to handle the `ALT` key press for GTK LAF and mimic the 
>> native behavior. Fix is similar to the `ALT` key processing in  Windows LAF. 
>> Automated test case is added to verify the fix and tested in Ubuntu and 
>> Oracle linux.
>> 
>> CI testing is green and link attached in JBS.
>
> Abhishek Kumar has updated the pull request incrementally with two additional 
> commits since the last revision:
> 
>  - Mnemonic handler class
>  - Mnemonic handler added and previous implementation revert back

I think we're moving in the right direction.

My idea was to extract the common functionality as the methods 
`setMnemonicHidden`, `isMnemonicHidden` and `repaintMnemonicsInWindow`, 
`repaintMnemonicsInContainer` into a helper class.

`AltProcessor`… Your version for GTK and the version in Aqua look the same to 
me. I think it makes sense to create a common `AltProcessor` class which would 
be used by GTK and Aqua.

The Windows version is different, so it'll stay this way… It doesn't look worth 
trying to fit that version into a shared class.

src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java 
line 1461:

> 1459: 
> 1460:         KeyboardFocusManager.getCurrentKeyboardFocusManager().
> 1461:                 addKeyEventPostProcessor(MnemonicHandler.altProcessor);

Suggestion:

        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(MnemonicHandler.altProcessor);

Better wrap the line before the dot operator — this conveys that it's a 
continuation of a call sequence rather than a wrapped parameter to a method.

src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java 
line 1469:

> 1467:     /**
> 1468:      * Called by UIManager when this look and feel is uninstalled.
> 1469:      */

Does it repeat the javadoc of the super class? Likely it does, use 
`{@inheritDoc}` instead.

src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java 
line 1470:

> 1468:      * Called by UIManager when this look and feel is uninstalled.
> 1469:      */
> 1470:     @Override

You may want to add the `@Override` annotation to `initialize` method too… for 
consistency.

src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java 
line 672:

> 670:                 int mnemIndex = 
> lh.getMenuItem().getDisplayedMnemonicIndex();
> 671:                 // Check to see if the Mnemonic should be rendered in 
> GTK.
> 672:                 if (mnemIndex >= 0 && 
> MnemonicHandler.isMnemonicHidden()) {

Is 0 a valid mnemonic? Probably not.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 40:

> 38: import javax.swing.UIManager;
> 39: 
> 40: public class MnemonicHandler {

Suggestion:

public final class MnemonicHandler {

It's an utility class that should not be extended. In addition to that, it 
should have a private constructor to prevent instantiating the class.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 41:

> 39: 
> 40: public class MnemonicHandler {
> 41:     public static final AltProcessor altProcessor = new AltProcessor();

I'd like to see `AltProcessor` here but it's different for Windows. Thus, 
`AltProcessor` should be local to `*RootUI` as it is now.

If `AltProcessor` in GTK and Aqua are similar or the same, it makes sense to 
extract them into a common helper class.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 43:

> 41:     public static final AltProcessor altProcessor = new AltProcessor();
> 42: 
> 43:     protected static boolean isMnemonicHidden;

Suggestion:

    private static boolean isMnemonicHidden;

It's accessed via `isMnemonicHidden` and `setMnemonicHidden`; since the class 
cannot be extended, it should not have protected members.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 103:

> 101:      * Repaints all the components with the mnemonics in the given 
> window and all its owned windows.
> 102:      */
> 103:     static void repaintMnemonicsInWindow(final Window w) {

Suggestion:

    public static void repaintMnemonicsInWindow(final Window w) {

This method would be called from `AltProcessor` class in the three different 
L&Fs, it should be `public`.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 120:

> 118:      * Recursively searches for all the subcomponents.
> 119:      */
> 120:     static void repaintMnemonicsInContainer(final Container cont) {

If `repaintMnemonicsInContainer` is never called directly but only from 
`repaintMnemonicsInWindow` above, the method should be `private`.

src/java.desktop/share/classes/sun/swing/MnemonicHandler.java line 131:

> 129:                 c.repaint();
> 130:                 continue;
> 131:             } else if (c instanceof Container) {

`continue` is redundant if you chain `if` block with `else if`.

If you remove `continue` from the first `if` block, it becomes empty, which 
isn't good. I suggest moving the first block into its own `if` statement:


if (c == null || !c.isVisible()) {
    continue;
}

if (/* other conditions */) {


You can use pattern matching to avoid explicit cast. Are we planning to 
backporting this change to JDK 11? If not, I'd go for pattern matching:


if (c instanceof AbstractButton b && b.getMnemonic() != '\0') {
    c.repaint();
}


Likely, the condition can be simplified further: the button and the label cases 
have the same body, and thus the two conditions can be combined into one 
condition.

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

Changes requested by aivanov (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/18992#pullrequestreview-2145923809
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657452729
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657450301
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657450931
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657448791
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657454306
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657457592
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657459171
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657461663
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657462542
PR Review Comment: https://git.openjdk.org/jdk/pull/18992#discussion_r1657470679

Reply via email to