8194873: right ALT key hotkeys no longer work in Swing components
authorpbansal
Mon, 25 Jun 2018 12:50:25 +0530
changeset 50837 86897f8a6598
parent 50836 b9456394d24f
child 50838 732a3b600098
8194873: right ALT key hotkeys no longer work in Swing components Reviewed-by: serb, psadhukhan
src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java
src/java.desktop/share/classes/sun/swing/SwingUtilities2.java
src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
test/jdk/javax/swing/event/RightAltKeyTest.java
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Mon Jun 25 12:50:25 2018 +0530
@@ -636,7 +636,9 @@
             "Menu.submenuPopupOffsetX", -2,
             "Menu.submenuPopupOffsetY", 3,
             "Menu.shortcutKeys", new int[]{
-                SwingUtilities2.getSystemMnemonicKeyMask(), metaMask
+                SwingUtilities2.getSystemMnemonicKeyMask(), metaMask,
+                SwingUtilities2.setAltGraphMask(
+                        SwingUtilities2.getSystemMnemonicKeyMask())
             },
             "Menu.cancelMode", "hideMenuTree",
 
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java	Mon Jun 25 12:50:25 2018 +0530
@@ -26,6 +26,7 @@
 package javax.swing.plaf.basic;
 
 import sun.swing.DefaultLookup;
+import sun.swing.SwingUtilities2;
 import sun.swing.UIAction;
 import java.awt.*;
 import java.awt.event.*;
@@ -156,8 +157,17 @@
             map.clear();
             map.put(KeyStroke.getKeyStroke(m, BasicLookAndFeel.getFocusAcceleratorKeyMask(), false),
                     "pressed");
+            map.put(KeyStroke.getKeyStroke(m, SwingUtilities2.setAltGraphMask
+                            (BasicLookAndFeel.getFocusAcceleratorKeyMask()),
+                    false),
+                    "pressed");
+
             map.put(KeyStroke.getKeyStroke(m, BasicLookAndFeel.getFocusAcceleratorKeyMask(), true),
                     "released");
+            map.put(KeyStroke.getKeyStroke(m,
+                    SwingUtilities2.setAltGraphMask
+                            (BasicLookAndFeel.getFocusAcceleratorKeyMask()), true),
+                    "released");
             map.put(KeyStroke.getKeyStroke(m, 0, true), "released");
         }
         else {
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java	Mon Jun 25 12:50:25 2018 +0530
@@ -36,6 +36,7 @@
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.Component;
 import java.awt.Container;
@@ -402,6 +403,10 @@
             }
             inputMap.clear();
             inputMap.put(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), false), "press");
+            inputMap.put(KeyStroke.getKeyStroke(dka,
+                    SwingUtilities2.setAltGraphMask (
+                            BasicLookAndFeel.getFocusAcceleratorKeyMask()),
+                    false), "press");
         }
         else {
             InputMap inputMap = SwingUtilities.getUIInputMap
@@ -520,6 +525,8 @@
                 int dka = label.getDisplayedMnemonic();
                 putOnRelease(inputMap, dka, BasicLookAndFeel
                         .getFocusAcceleratorKeyMask());
+                putOnRelease(inputMap, dka, SwingUtilities2.setAltGraphMask (
+                        BasicLookAndFeel.getFocusAcceleratorKeyMask()));
                 // Need this when the sticky keys are enabled
                 putOnRelease(inputMap, dka, 0);
                 // Need this if ALT is released before the accelerator
@@ -539,6 +546,9 @@
                         int dka = label.getDisplayedMnemonic();
                         removeOnRelease(inputMap, dka, BasicLookAndFeel
                                 .getFocusAcceleratorKeyMask());
+                        removeOnRelease(inputMap, dka,
+                                SwingUtilities2.setAltGraphMask (
+                                BasicLookAndFeel.getFocusAcceleratorKeyMask()));
                         removeOnRelease(inputMap, dka, 0);
                         removeOnRelease(inputMap, KeyEvent.VK_ALT, 0);
                     }
@@ -555,6 +565,9 @@
                     } else {
                         putOnRelease(inputMap, dka, BasicLookAndFeel
                                 .getFocusAcceleratorKeyMask());
+                        putOnRelease(inputMap, dka,
+                                SwingUtilities2.setAltGraphMask (
+                                BasicLookAndFeel.getFocusAcceleratorKeyMask()));
                         // Need this when the sticky keys are enabled
                         putOnRelease(inputMap, dka, 0);
                     }
@@ -572,6 +585,9 @@
                         if (isCommand) {
                             removeOnRelease(inputMap, dka, BasicLookAndFeel
                                     .getFocusAcceleratorKeyMask());
+                            removeOnRelease(inputMap, dka,
+                                    SwingUtilities2.setAltGraphMask (
+                                    BasicLookAndFeel.getFocusAcceleratorKeyMask()));
                             removeOnRelease(inputMap, dka, 0);
                         } else {
                             removeOnRelease(inputMap, KeyEvent.VK_ALT, 0);
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java	Mon Jun 25 12:50:25 2018 +0530
@@ -1093,7 +1093,9 @@
             "Menu.submenuPopupOffsetX", 0,
             "Menu.submenuPopupOffsetY", 0,
             "Menu.shortcutKeys", new int[]{
-                SwingUtilities2.getSystemMnemonicKeyMask()
+                SwingUtilities2.getSystemMnemonicKeyMask(),
+                SwingUtilities2.setAltGraphMask(
+                        SwingUtilities2.getSystemMnemonicKeyMask())
             },
             "Menu.crossMenuMnemonic", Boolean.TRUE,
             // Menu.cancelMode affects the cancel menu action behaviour;
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java	Mon Jun 25 12:50:25 2018 +0530
@@ -434,6 +434,7 @@
         return null;
     }
 
+    @SuppressWarnings("deprecation")
     void updateAcceleratorBinding() {
         KeyStroke accelerator = menuItem.getAccelerator();
         InputMap windowInputMap = SwingUtilities.getUIInputMap(
@@ -450,6 +451,45 @@
                            JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap);
             }
             windowInputMap.put(accelerator, "doClick");
+
+            int modifiers = accelerator.getModifiers();
+            if (((modifiers & InputEvent.ALT_DOWN_MASK) != 0) &&
+                    ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0)) {
+                //When both ALT and ALT_GRAPH are set, add the ALT only
+                // modifier keystroke which is used for left ALT key.
+                // Unsetting the ALT_GRAPH will do that as ALT is already set
+                modifiers &= ~InputEvent.ALT_GRAPH_DOWN_MASK;
+                modifiers &= ~InputEvent.ALT_GRAPH_MASK;
+                KeyStroke keyStroke = KeyStroke.getKeyStroke(accelerator.getKeyCode(),
+                        modifiers, accelerator.isOnKeyRelease());
+                windowInputMap.put(keyStroke, "doClick");
+            } else if (((modifiers & InputEvent.ALT_DOWN_MASK) != 0) && (
+                    (modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) == 0)) {
+                //When only ALT modifier is set, add the ALT + ALT_GRAPH
+                // modifier keystroke which is used for right ALT key
+                modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
+                KeyStroke keyStroke = KeyStroke.getKeyStroke(accelerator.getKeyCode(),
+                        modifiers, accelerator.isOnKeyRelease());
+                windowInputMap.put(keyStroke, "doClick");
+            } else if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
+                //When only ALT_GRAPH is set, remove the ALT_GRAPH only
+                // modifier and add the ALT and ALT+ALT_GRAPH modifiers
+                // keystroke which are used for left ALT key and right ALT
+                // respectively
+                modifiers &= ~InputEvent.ALT_GRAPH_DOWN_MASK;
+                modifiers &= ~InputEvent.ALT_GRAPH_MASK;
+
+                modifiers |= InputEvent.ALT_DOWN_MASK;
+                KeyStroke keyStroke = KeyStroke.getKeyStroke(accelerator.getKeyCode(),
+                        modifiers, accelerator.isOnKeyRelease());
+                windowInputMap.put(keyStroke, "doClick");
+
+                //Add ALT+ALT_GRAPH modifier which is used for right ALT key
+                modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
+                keyStroke = KeyStroke.getKeyStroke(accelerator.getKeyCode(),
+                        modifiers, accelerator.isOnKeyRelease());
+                windowInputMap.put(keyStroke, "doClick");
+            }
         }
     }
 
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java	Mon Jun 25 12:50:25 2018 +0530
@@ -129,7 +129,8 @@
         int[] shortcutKeys = (int[])DefaultLookup.get(menuItem, this,
                                                    "Menu.shortcutKeys");
         if (shortcutKeys == null) {
-            shortcutKeys = new int[] {KeyEvent.ALT_MASK};
+            shortcutKeys = new int[] {KeyEvent.ALT_MASK,
+                    KeyEvent.ALT_MASK | KeyEvent.ALT_GRAPH_MASK};
         }
         if (mnemonic == lastMnemonic) {
             return;
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	Mon Jun 25 12:50:25 2018 +0530
@@ -606,6 +606,10 @@
         }
         mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, BasicLookAndFeel.getFocusAcceleratorKeyMask()),
                              "setSelectedIndex");
+        mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic,
+                SwingUtilities2.setAltGraphMask(
+                        BasicLookAndFeel.getFocusAcceleratorKeyMask())),
+                "setSelectedIndex");
         mnemonicToIndexMap.put(Integer.valueOf(mnemonic), Integer.valueOf(index));
     }
 
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java	Mon Jun 25 12:50:25 2018 +0530
@@ -42,6 +42,8 @@
 import javax.swing.plaf.synth.SynthUI;
 import sun.swing.DefaultLookup;
 import sun.awt.AppContext;
+import sun.swing.SwingUtilities2;
+
 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag;
 
 /**
@@ -511,6 +513,10 @@
                 km.clear();
                 if (accelerator != '\0') {
                     km.put(KeyStroke.getKeyStroke(accelerator, BasicLookAndFeel.getFocusAcceleratorKeyMask()), "requestFocus");
+                    km.put(KeyStroke.getKeyStroke(accelerator,
+                            SwingUtilities2.setAltGraphMask(
+                            BasicLookAndFeel.getFocusAcceleratorKeyMask())),
+                            "requestFocus");
                 }
             }
         }
--- a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java	Mon Jun 25 12:50:25 2018 +0530
@@ -2139,6 +2139,15 @@
         return -1;
     }
 
+    /**
+     * Sets the InputEvent.ALT_GRAPH mask on any modifier passed to the function
+     * @param modifier the modifier passed
+     * @return the modifier retiurned with ALT_GRAPH flag set
+     */
+    public static int setAltGraphMask(int modifier) {
+        return (modifier | InputEvent.ALT_GRAPH_DOWN_MASK);
+    }
+
     @SuppressWarnings("deprecation")
     public static int getSystemMnemonicKeyMask() {
         Toolkit toolkit = Toolkit.getDefaultToolkit();
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Mon Jun 25 16:01:01 2018 +0530
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Mon Jun 25 12:50:25 2018 +0530
@@ -3537,15 +3537,10 @@
     BOOL shiftIsDown = FALSE;
     if (modifiers) {
         shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
-        BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
+        BOOL altIsDown = ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) ||
+                            (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK));
         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
 
-        // Windows treats AltGr as Ctrl+Alt
-        if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
-            altIsDown = TRUE;
-            ctrlIsDown = TRUE;
-        }
-
         if (shiftIsDown) {
             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/event/RightAltKeyTest.java	Mon Jun 25 12:50:25 2018 +0530
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @key headful
+ * @bug 8194873
+ * @requires (os.family == "Windows")
+ * @summary Checks that right ALT (ALT_GRAPH) key works on Swing components
+ * @run main RightAltKeyTest
+ */
+
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextField;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.KeyStroke;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.GridLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+
+public class RightAltKeyTest {
+
+    boolean action = false;
+    JFrame frame;
+
+    void testJMenu() {
+        frame = new JFrame("Menu Frame");
+        JMenuBar mb = new JMenuBar();
+        JMenu m1 = new JMenu("File");
+        JMenuItem i1 = new JMenuItem("Save");
+        JMenuItem i2 = new JMenuItem("Load");
+
+        m1.setMnemonic(KeyEvent.VK_F);
+
+        m1.addMenuListener(new MenuListener() {
+            @Override
+            public void menuSelected(MenuEvent e) {
+                action = true;
+                disposeUI();
+            }
+
+            @Override
+            public void menuDeselected(MenuEvent e) {
+            }
+
+            @Override
+            public void menuCanceled(MenuEvent e) {
+            }
+        });
+
+        frame.setJMenuBar(mb);
+        mb.add(m1);
+        m1.add(i1);
+        m1.add(i2);
+
+        frame.setSize(200, 200);
+        frame.setVisible(true);
+    }
+
+    void testJMenuItem() {
+        frame = new JFrame("Menu Frame");
+        JMenuBar mb = new JMenuBar();
+        JMenu m1 = new JMenu("File");
+        JMenuItem i1 = new JMenuItem("Save");
+        i1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
+                InputEvent.ALT_GRAPH_DOWN_MASK));
+        i1.addActionListener((e) -> {
+            action = true;
+            disposeUI();
+        });
+
+        frame.setJMenuBar(mb);
+        mb.add(m1);
+        m1.add(i1);
+
+        frame.setSize(200, 200);
+        frame.setVisible(true);
+    }
+
+    void testJOptionPane() {
+        int selection =  JOptionPane.showConfirmDialog(null, "Do you wish " +
+                "to save file?","Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
+        //Pressed Yes
+        if (selection == 0) {
+            action = true;
+        }
+    }
+
+    void testJTabbedPane() {
+        frame =new JFrame();
+        JPanel p1=new JPanel();
+        JPanel p2=new JPanel();
+        JTabbedPane tp=new JTabbedPane();
+        tp.add("Main",p1);
+        tp.add("Visit",p2);
+        tp.setMnemonicAt(0, KeyEvent.VK_M);
+        tp.setMnemonicAt(1, KeyEvent.VK_V);
+
+        tp.addChangeListener((e) -> {
+            if (tp.getSelectedIndex() == 1)
+                action = true;
+            disposeUI();
+        });
+
+        frame.add(tp);
+        frame.setSize(200,200);
+        frame.setVisible(true);
+    }
+
+    void testJTextArea() {
+        JTextField firstField = new JTextField(10);
+        JTextField lastField = new JTextField(10);
+
+        JLabel firstLabel = new JLabel("First Name", JLabel.RIGHT);
+        firstLabel.setDisplayedMnemonic('F');
+        firstLabel.setLabelFor(firstField);
+
+        JLabel lastLabel = new JLabel("Last Name", JLabel.RIGHT);
+        lastLabel.setDisplayedMnemonic('L');
+        lastLabel.setLabelFor(lastField);
+
+        JPanel p = new JPanel();
+        p.setLayout(new GridLayout(2, 2, 5, 5));
+        p.add(firstLabel);
+        p.add(firstField);
+        p.add(lastLabel);
+        p.add(lastField);
+
+        frame = new JFrame("MnemonicLabels");
+        lastField.addFocusListener(new FocusListener() {
+            @Override
+            public void focusGained(FocusEvent e) {
+                action = true;
+                disposeUI();
+            }
+
+            @Override
+            public void focusLost(FocusEvent e) {
+
+            }
+        });
+
+        frame.add(p);
+        frame.setSize(200,200);
+        frame.setVisible(true);
+    }
+
+    void test() throws Exception {
+        UIManager.LookAndFeelInfo[] lookAndFeels = UIManager
+                .getInstalledLookAndFeels();
+        for (UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels) {
+            UIManager.setLookAndFeel(lookAndFeel.getClassName());
+
+            Robot robot = new Robot();
+            robot.setAutoDelay(100);
+            robot.waitForIdle();
+
+            action = false;
+            SwingUtilities.invokeLater(this::testJMenu);
+            robot.waitForIdle();
+            robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+            robot.keyPress(KeyEvent.VK_F);
+            robot.keyRelease(KeyEvent.VK_F);
+            robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+            robot.waitForIdle();
+            if (!action)
+                errLog("JMenu", lookAndFeel.getClassName());
+
+            action = false;
+            SwingUtilities.invokeLater(this::testJMenuItem);
+            robot.waitForIdle();
+            robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+            robot.keyPress(KeyEvent.VK_S);
+            robot.keyRelease(KeyEvent.VK_S);
+            robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+            robot.waitForIdle();
+            if (!action)
+                errLog("JMenuItem", lookAndFeel.getClassName());
+
+            action = false;
+            SwingUtilities.invokeLater(this::testJOptionPane);
+            robot.waitForIdle();
+            robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+            robot.keyPress(KeyEvent.VK_Y);
+            robot.keyRelease(KeyEvent.VK_Y);
+            robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+            robot.waitForIdle();
+            if (!action)
+                errLog("JOptionPane", lookAndFeel.getClassName());
+
+            action = false;
+            SwingUtilities.invokeLater(this::testJTabbedPane);
+            robot.waitForIdle();
+            robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+            robot.keyPress(KeyEvent.VK_V);
+            robot.keyRelease(KeyEvent.VK_V);
+            robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+            robot.waitForIdle();
+            if (!action)
+                errLog("JTabbedPane", lookAndFeel.getClassName());
+
+            action = false;
+            SwingUtilities.invokeLater(this::testJTextArea);
+            robot.waitForIdle();
+            robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+            robot.keyPress(KeyEvent.VK_L);
+            robot.keyRelease(KeyEvent.VK_L);
+            robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+            robot.waitForIdle();
+            if (!action)
+                errLog("JTextArea", lookAndFeel.getClassName());
+        }
+        System.out.println("Passed.");
+    }
+
+    void disposeUI() {
+        frame.setVisible(false);
+        frame.dispose();
+    }
+
+    void errLog(String componentName, String lookAndFeel)
+            throws InvocationTargetException, InterruptedException
+    {
+        SwingUtilities.invokeAndWait(this::disposeUI);
+        throw new RuntimeException("Actions are not performed for "+
+                componentName + " with " + lookAndFeel + " look and feel.");
+    }
+
+    public static void main(String[] args) throws Exception {
+        RightAltKeyTest t = new RightAltKeyTest();
+        t.test();
+    }
+}