7199180: [macosx] Dead keys handling for input methods
authoralexsch
Fri, 21 Sep 2012 13:48:06 +0400
changeset 13990 3e72145fd93a
parent 13989 0927753651cf
child 13991 e62879b84a14
7199180: [macosx] Dead keys handling for input methods Reviewed-by: kizune, anthony
jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
jdk/src/macosx/native/sun/awt/AWTEvent.m
jdk/src/macosx/native/sun/awt/AWTView.m
jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Thu Sep 20 17:55:40 2012 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Fri Sep 21 13:48:06 2012 +0400
@@ -160,6 +160,9 @@
 
             if(isDeadChar){
                 testChar = (char) out[2];
+                if(testChar == 0){
+                    return;
+                }
             }
 
             jkeyCode = out[0];
--- a/jdk/src/macosx/native/sun/awt/AWTEvent.m	Thu Sep 20 17:55:40 2012 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m	Fri Sep 21 13:48:06 2012 +0400
@@ -383,6 +383,7 @@
 {
     TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
     CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
+    if (uchr == nil) { return; }
     const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
     // Carbon modifiers should be used instead of NSEvent modifiers
     UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF;
@@ -563,18 +564,18 @@
     const struct _nsKeyToJavaModifier* cur;
 
     for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
-        jint mask = isExtMods? cur->javaExtMask : cur->javaMask; 
+        jint mask = isExtMods? cur->javaExtMask : cur->javaMask;
         if ((mask & javaModifiers) != 0) {
             nsFlags |= cur->nsMask;
         }
     }
 
     // special case
-    jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK : 
+    jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK :
                            java_awt_event_InputEvent_ALT_GRAPH_MASK;
 
     if ((mask & javaModifiers) != 0) {
-        nsFlags |= NSAlternateKeyMask;      
+        nsFlags |= NSAlternateKeyMask;
     }
 
     return nsFlags;
--- a/jdk/src/macosx/native/sun/awt/AWTView.m	Thu Sep 20 17:55:40 2012 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m	Fri Sep 21 13:48:06 2012 +0400
@@ -279,7 +279,10 @@
         return;
     }
 
-    if (![self hasMarkedText] && fKeyEventsNeeded) {
+    NSString *eventCharacters = [event characters];
+    BOOL isDeadKey = (eventCharacters != nil && [eventCharacters length] == 0);
+
+    if ((![self hasMarkedText] && fKeyEventsNeeded) || isDeadKey) {
         [self deliverJavaKeyEventHelper: event];
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java	Fri Sep 21 13:48:06 2012 +0400
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012, 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
+ * @bug 7199180
+ * @summary [macosx] Dead keys handling for input methods
+ * @author alexandr.scherbatiy area=awt.event
+ * @run main DeadKeyMacOSXInputText
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.event.KeyEvent;
+import javax.swing.JTextField;
+import sun.awt.OSInfo;
+import sun.awt.SunToolkit;
+
+public class DeadKeyMacOSXInputText {
+
+    private static SunToolkit toolkit;
+    private static volatile int state = 0;
+
+    public static void main(String[] args) throws Exception {
+
+        if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) {
+            return;
+        }
+
+        toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+
+        createAndShowGUI();
+
+        // Pressed keys: Alt + E + A
+        // Results:  ALT + VK_DEAD_ACUTE + a with accute accent
+        robot.keyPress(KeyEvent.VK_ALT);
+        robot.keyPress(KeyEvent.VK_E);
+        robot.keyRelease(KeyEvent.VK_E);
+        robot.keyRelease(KeyEvent.VK_ALT);
+
+        robot.keyPress(KeyEvent.VK_A);
+        robot.keyRelease(KeyEvent.VK_A);
+        toolkit.realSync();
+
+        if (state != 3) {
+            throw new RuntimeException("Wrong number of key events.");
+        }
+    }
+
+    static void createAndShowGUI() {
+        Frame frame = new Frame();
+        frame.setSize(300, 300);
+        Panel panel = new Panel(new BorderLayout());
+        JTextField textField = new JTextField();
+        textField.addKeyListener(new DeadKeyListener());
+        panel.add(textField, BorderLayout.CENTER);
+        frame.add(panel);
+        frame.setVisible(true);
+        toolkit.realSync();
+
+        textField.requestFocusInWindow();
+        toolkit.realSync();
+
+    }
+
+    static class DeadKeyListener extends KeyAdapter {
+
+        @Override
+        public void keyPressed(KeyEvent e) {
+            int keyCode = e.getKeyCode();
+            char keyChar = e.getKeyChar();
+
+            switch (state) {
+                case 0:
+                    if (keyCode != KeyEvent.VK_ALT) {
+                        throw new RuntimeException("Alt is not pressed.");
+                    }
+                    state++;
+                    break;
+                case 1:
+                    if (keyCode != KeyEvent.VK_DEAD_ACUTE) {
+                        throw new RuntimeException("Dead ACUTE is not pressed.");
+                    }
+                    if (keyChar != 0xB4) {
+                        throw new RuntimeException("Pressed char is not dead acute.");
+                    }
+                    state++;
+                    break;
+            }
+        }
+
+        @Override
+        public void keyTyped(KeyEvent e) {
+            int keyCode = e.getKeyCode();
+            char keyChar = e.getKeyChar();
+
+            if (state == 2) {
+                if (keyCode != 0) {
+                    throw new RuntimeException("Key code should be undefined.");
+                }
+                if (keyChar != 0xE1) {
+                    throw new RuntimeException("A char does not have ACCUTE accent");
+                }
+                state++;
+            } else {
+                throw new RuntimeException("Wron number of keyTyped events.");
+            }
+        }
+    }
+}