diff --git a/jdk/src/macosx/native/sun/awt/AWTEvent.h b/jdk/src/macosx/native/sun/awt/AWTEvent.h index f813b8c7d00..7769f3d4163 100644 --- a/jdk/src/macosx/native/sun/awt/AWTEvent.h +++ b/jdk/src/macosx/native/sun/awt/AWTEvent.h @@ -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 @@ void SendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer); 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 */ diff --git a/jdk/src/macosx/native/sun/awt/AWTEvent.m b/jdk/src/macosx/native/sun/awt/AWTEvent.m index 7bde46f1709..fd3caa6051f 100644 --- a/jdk/src/macosx/native/sun/awt/AWTEvent.m +++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m @@ -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 @@ const charTable[] = { {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. diff --git a/jdk/src/macosx/native/sun/awt/CMenuItem.m b/jdk/src/macosx/native/sun/awt/CMenuItem.m index b67c70658dd..eaabb3e06ab 100644 --- a/jdk/src/macosx/native/sun/awt/CMenuItem.m +++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m @@ -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 @@ AWT_ASSERT_APPKIT_THREAD; 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; } diff --git a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java index 47761ec13d2..4cf1c750da5 100644 --- a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java +++ b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java @@ -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 java.awt.event.*; 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"); - menu.add(newItem); + + 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++; + } + } + ); + menu.add(newItem); + } + JMenuBar bar = new JMenuBar(); bar.add(menu); JFrame frame = new JFrame("Test"); @@ -80,4 +109,24 @@ public class ActionListenerCalledTwiceTest { 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; + } }