8008366: [macosx] ActionListener called twice for JMenuItem using ScreenMenuBar
Reviewed-by: anthony, serb
--- a/jdk/src/macosx/native/sun/awt/AWTEvent.h Mon Apr 22 18:39:04 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTEvent.h Mon Apr 22 19:24:41 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -35,5 +35,6 @@
jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags);
jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods);
NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods);
+unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers);
#endif /* __AWTEVENT_H */
--- a/jdk/src/macosx/native/sun/awt/AWTEvent.m Mon Apr 22 18:39:04 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m Mon Apr 22 19:24:41 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -341,8 +341,7 @@
{0, 0, 0}
};
-static unichar
-NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
+unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
{
const struct _char *cur;
// Mask off just the keyboard modifiers from the event modifier mask.
--- a/jdk/src/macosx/native/sun/awt/CMenuItem.m Mon Apr 22 18:39:04 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m Mon Apr 22 19:24:41 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -71,12 +71,21 @@
JNF_COCOA_ENTER(env);
// If we are called as a result of user pressing a shorcut, do nothing,
- // because AVTView has already sent corresponding key event to the Java
+ // because AVTView has already sent corresponding key event to the Java
// layer from performKeyEquivalent
NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
if ([currEvent type] == NSKeyDown) {
NSString *menuKey = [sender keyEquivalent];
NSString *eventKey = [currEvent charactersIgnoringModifiers];
+
+ // Apple uses characters from private Unicode range for some of the
+ // keys, so we need to do the same translation here that we do
+ // for the regular key down events
+ if ([eventKey length] == 1) {
+ unichar ch = NsCharToJavaChar([eventKey characterAtIndex:0], 0);
+ eventKey = [NSString stringWithCharacters: &ch length: 1];
+ }
+
if ([menuKey isEqualToString:eventKey]) {
return;
}
--- a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java Mon Apr 22 18:39:04 2013 +0400
+++ b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java Mon Apr 22 19:24:41 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -35,43 +35,72 @@
import javax.swing.*;
public class ActionListenerCalledTwiceTest {
+ static String menuItems[] = { "Item1", "Item2" };
+ static KeyStroke keyStrokes[] = {
+ KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.META_MASK),
+ KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)
+ };
+
static volatile int listenerCallCounter = 0;
public static void main(String[] args) throws Exception {
if (sun.awt.OSInfo.getOSType() != sun.awt.OSInfo.OSType.MACOSX) {
System.out.println("This test is for MacOS only. Automatically passed on other platforms.");
return;
}
+
System.setProperty("apple.laf.useScreenMenuBar", "true");
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createAndShowGUI();
}
});
+
SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
Robot robot = new Robot();
robot.setAutoDelay(100);
- robot.keyPress(KeyEvent.VK_META);
- robot.keyPress(KeyEvent.VK_E);
- robot.keyRelease(KeyEvent.VK_E);
- robot.keyRelease(KeyEvent.VK_META);
- toolkit.realSync();
- if (listenerCallCounter != 1) {
- throw new Exception("Test failed: ActionListener called " + listenerCallCounter + " times instead of 1!");
+
+ for (int i = 0; i < menuItems.length; ++i) {
+ KeyStroke ks = keyStrokes[i];
+ int modKeyCode = getModKeyCode(ks.getModifiers());
+
+ if (modKeyCode != 0) {
+ robot.keyPress(modKeyCode);
+ }
+
+ robot.keyPress(ks.getKeyCode());
+ robot.keyRelease(ks.getKeyCode());
+
+ if (modKeyCode != 0) {
+ robot.keyRelease(modKeyCode);
+ }
+
+ toolkit.realSync();
+
+ if (listenerCallCounter != 1) {
+ throw new Exception("Test failed: ActionListener for " + menuItems[i] +
+ " called " + listenerCallCounter + " times instead of 1!");
+ }
+
+ listenerCallCounter = 0;
}
}
private static void createAndShowGUI() {
- JMenuItem newItem = new JMenuItem("Exit");
- newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.META_MASK));
- newItem.addActionListener(
- new ActionListener(){
- public void actionPerformed(ActionEvent e) {
- listenerCallCounter++;
+ JMenu menu = new JMenu("Menu");
+
+ for (int i = 0; i < menuItems.length; ++i) {
+ JMenuItem newItem = new JMenuItem(menuItems[i]);
+ newItem.setAccelerator(keyStrokes[i]);
+ newItem.addActionListener(
+ new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ listenerCallCounter++;
+ }
}
- }
- );
- JMenu menu = new JMenu("Menu");
- menu.add(newItem);
+ );
+ menu.add(newItem);
+ }
+
JMenuBar bar = new JMenuBar();
bar.add(menu);
JFrame frame = new JFrame("Test");
@@ -80,4 +109,24 @@
frame.pack();
frame.setVisible(true);
}
+
+ private static int getModKeyCode(int mod) {
+ if ((mod & (InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)) != 0) {
+ return KeyEvent.VK_SHIFT;
+ }
+
+ if ((mod & (InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)) != 0) {
+ return KeyEvent.VK_CONTROL;
+ }
+
+ if ((mod & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)) != 0) {
+ return KeyEvent.VK_ALT;
+ }
+
+ if ((mod & (InputEvent.META_DOWN_MASK | InputEvent.META_MASK)) != 0) {
+ return KeyEvent.VK_META;
+ }
+
+ return 0;
+ }
}