Skip to content

Commit 1ea81a7

Browse files
committed
8225505: ctrl-F1 does not show the tooltip of a menu item (JMenuItems)
Reviewed-by: psadhukhan, serb
1 parent 07e2ea8 commit 1ea81a7

File tree

2 files changed

+188
-5
lines changed

2 files changed

+188
-5
lines changed

src/java.desktop/share/classes/javax/swing/ToolTipManager.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
2929
import java.awt.event.*;
3030
import java.awt.*;
3131
import java.util.Objects;
32+
import javax.swing.event.MenuKeyEvent;
33+
import javax.swing.event.MenuKeyListener;
3234

3335
/**
3436
* Manages all the <code>ToolTips</code> in the system.
@@ -415,8 +417,14 @@ public void registerComponent(JComponent component) {
415417
component.addMouseListener(this);
416418
component.removeMouseMotionListener(moveBeforeEnterListener);
417419
component.addMouseMotionListener(moveBeforeEnterListener);
418-
component.removeKeyListener(accessibilityKeyListener);
419-
component.addKeyListener(accessibilityKeyListener);
420+
// use MenuKeyListener for menu items/elements
421+
if (component instanceof JMenuItem) {
422+
((JMenuItem) component).removeMenuKeyListener((MenuKeyListener) accessibilityKeyListener);
423+
((JMenuItem) component).addMenuKeyListener((MenuKeyListener) accessibilityKeyListener);
424+
} else {
425+
component.removeKeyListener(accessibilityKeyListener);
426+
component.addKeyListener(accessibilityKeyListener);
427+
}
420428
}
421429

422430
/**
@@ -427,7 +435,11 @@ public void registerComponent(JComponent component) {
427435
public void unregisterComponent(JComponent component) {
428436
component.removeMouseListener(this);
429437
component.removeMouseMotionListener(moveBeforeEnterListener);
430-
component.removeKeyListener(accessibilityKeyListener);
438+
if (component instanceof JMenuItem) {
439+
((JMenuItem) component).removeMenuKeyListener((MenuKeyListener) accessibilityKeyListener);
440+
} else {
441+
component.removeKeyListener(accessibilityKeyListener);
442+
}
431443
}
432444

433445
// implements java.awt.event.MouseListener
@@ -867,7 +879,7 @@ private void hide(JComponent source) {
867879
* Post Tip: Ctrl+F1
868880
* Unpost Tip: Esc and Ctrl+F1
869881
*/
870-
private class AccessibilityKeyListener extends KeyAdapter {
882+
private class AccessibilityKeyListener extends KeyAdapter implements MenuKeyListener {
871883
public void keyPressed(KeyEvent e) {
872884
if (!e.isConsumed()) {
873885
JComponent source = (JComponent) e.getComponent();
@@ -884,5 +896,32 @@ public void keyPressed(KeyEvent e) {
884896
}
885897
}
886898
}
899+
900+
@Override
901+
public void menuKeyTyped(MenuKeyEvent e) {}
902+
903+
@Override
904+
public void menuKeyPressed(MenuKeyEvent e) {
905+
if (postTip.equals(KeyStroke.getKeyStrokeForEvent(e))) {
906+
// get element for the event
907+
MenuElement path[] = e.getPath();
908+
MenuElement element = path[path.length - 1];
909+
910+
// retrieve currently highlighted element
911+
MenuSelectionManager msm = e.getMenuSelectionManager();
912+
MenuElement selectedPath[] = msm.getSelectedPath();
913+
MenuElement selectedElement = selectedPath[selectedPath.length - 1];
914+
915+
if (element.equals(selectedElement)) {
916+
// show/hide tooltip message
917+
JComponent source = (JComponent) element.getComponent();
918+
ToolTipManager.this.show(source);
919+
e.consume();
920+
}
921+
}
922+
}
923+
924+
@Override
925+
public void menuKeyReleased(MenuKeyEvent e) {}
887926
}
888927
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/* @test
25+
* @key headful
26+
* @bug 8225505
27+
* @summary CTRL + 1 does not show tooltip message for menu items
28+
* @run main/manual JMenuItemToolTipKeyBindingsTest
29+
*/
30+
31+
import javax.swing.JFrame;
32+
import javax.swing.JMenu;
33+
import javax.swing.JMenuBar;
34+
import javax.swing.JMenuItem;
35+
import javax.swing.SwingUtilities;
36+
import java.awt.Button;
37+
import java.awt.Dialog;
38+
import java.awt.Panel;
39+
import java.awt.TextArea;
40+
import java.awt.event.ActionEvent;
41+
import java.awt.event.ActionListener;
42+
import java.util.concurrent.atomic.AtomicBoolean;
43+
44+
public class JMenuItemToolTipKeyBindingsTest {
45+
private static final long TIMEOUT = 5 * 60 * 1000;
46+
private static final AtomicBoolean testCompleted = new AtomicBoolean(false);
47+
private static volatile boolean testResult = false;
48+
49+
private static Dialog controlDialog;
50+
private static JFrame testFrame;
51+
52+
private static final String instructions =
53+
"Verify that \"CTRL\" + \"F1\" key sequence shows/hides tool tip message" +
54+
"\nfor menu items.\n" +
55+
"\n1. Open pop-up menu \"Menu\", (i.e. press \"F10\")." +
56+
"\n2. Navigate to some menu element using keyboard." +
57+
"\n3. Press \"CTRL\" + \"F1\" once menu item is selected." +
58+
"\nIf tooltip message is displayed for the item then press \"Pass\"," +
59+
"\n otherwise press \"Fail\".";
60+
61+
public static void main(String[] args) throws Exception {
62+
try {
63+
SwingUtilities.invokeAndWait(() -> createAndShowGUI());
64+
65+
waitForCompleting();
66+
if (!testResult) {
67+
throw new RuntimeException("Test FAILED!");
68+
}
69+
} finally {
70+
if (controlDialog != null) {
71+
controlDialog.dispose();
72+
}
73+
if (testFrame != null) {
74+
testFrame.dispose();
75+
}
76+
}
77+
}
78+
79+
private static void createAndShowGUI() {
80+
controlDialog = new Dialog((JFrame)null, "JMenuItemToolTipKeyBindingsTest");
81+
82+
TextArea messageArea = new TextArea(instructions, 15, 80, TextArea.SCROLLBARS_BOTH);
83+
controlDialog.add("North", messageArea);
84+
85+
Button passedButton = new Button("Pass");
86+
passedButton.addActionListener(new ActionListener() {
87+
@Override
88+
public void actionPerformed(ActionEvent e) {
89+
testResult = true;
90+
completeTest();
91+
}
92+
});
93+
94+
Button failedButton = new Button("Fail");
95+
failedButton.addActionListener(new ActionListener() {
96+
@Override
97+
public void actionPerformed(ActionEvent e) {
98+
testResult = false;
99+
completeTest();
100+
}
101+
});
102+
103+
Panel buttonPanel = new Panel();
104+
buttonPanel.add("West",passedButton);
105+
buttonPanel.add("East", failedButton);
106+
controlDialog.add("South", buttonPanel);
107+
108+
controlDialog.setBounds(250, 0, 500, 500);
109+
controlDialog.setVisible(true);
110+
111+
testFrame = new JFrame("JMenuItemToolTipKeyBindingsTest");
112+
testFrame.setSize(200, 200);
113+
JMenuBar jMenuBar = new JMenuBar();
114+
JMenu jMenu = new JMenu("Menu");
115+
for (int i = 0; i < 3; i++) {
116+
JMenuItem jMenuItem = new JMenuItem("Item " + i);
117+
jMenuItem.setToolTipText("Tooltip " + i);
118+
jMenu.add(jMenuItem);
119+
}
120+
jMenuBar.add(jMenu);
121+
testFrame.setJMenuBar(jMenuBar);
122+
testFrame.setVisible(true);
123+
}
124+
125+
private static void completeTest() {
126+
testCompleted.set(true);
127+
synchronized (testCompleted) {
128+
testCompleted.notifyAll();
129+
}
130+
}
131+
132+
private static void waitForCompleting() throws Exception {
133+
synchronized (testCompleted) {
134+
long startTime = System.currentTimeMillis();
135+
while (!testCompleted.get()) {
136+
testCompleted.wait(TIMEOUT);
137+
if (System.currentTimeMillis() - startTime >= TIMEOUT) {
138+
break;
139+
}
140+
}
141+
}
142+
}
143+
}
144+

0 commit comments

Comments
 (0)