提交 121fc455 编写于 作者: A alexsch

7196547: [macosx] Implement dead key detection for KeyEvent

Reviewed-by: skovatch, kizune
上级 f6fed5e6
...@@ -134,7 +134,7 @@ final class CPlatformResponder { ...@@ -134,7 +134,7 @@ final class CPlatformResponder {
boolean postsTyped = false; boolean postsTyped = false;
char testChar = KeyEvent.CHAR_UNDEFINED; char testChar = KeyEvent.CHAR_UNDEFINED;
char testDeadChar = 0; boolean isDeadChar = (chars!= null && chars.length() == 0);
if (isFlagsChangedEvent) { if (isFlagsChangedEvent) {
int[] in = new int[] {modifierFlags, keyCode}; int[] in = new int[] {modifierFlags, keyCode};
...@@ -150,14 +150,18 @@ final class CPlatformResponder { ...@@ -150,14 +150,18 @@ final class CPlatformResponder {
testChar = chars.charAt(0); testChar = chars.charAt(0);
} }
int[] in = new int[] {testChar, testDeadChar, modifierFlags, keyCode}; int[] in = new int[] {testChar, isDeadChar ? 1 : 0, modifierFlags, keyCode};
int[] out = new int[2]; // [jkeyCode, jkeyLocation] int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar]
postsTyped = NSEvent.nsToJavaKeyInfo(in, out); postsTyped = NSEvent.nsToJavaKeyInfo(in, out);
if (!postsTyped) { if (!postsTyped) {
testChar = KeyEvent.CHAR_UNDEFINED; testChar = KeyEvent.CHAR_UNDEFINED;
} }
if(isDeadChar){
testChar = (char) out[2];
}
jkeyCode = out[0]; jkeyCode = out[0];
jkeyLocation = out[1]; jkeyLocation = out[1];
jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(eventType) : jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(eventType) :
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#import <JavaNativeFoundation/JavaNativeFoundation.h> #import <JavaNativeFoundation/JavaNativeFoundation.h>
#import <JavaRuntimeSupport/JavaRuntimeSupport.h> #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
#import <sys/time.h> #import <sys/time.h>
#include <Carbon/Carbon.h>
#import "LWCToolkit.h" #import "LWCToolkit.h"
#import "ThreadUtilities.h" #import "ThreadUtilities.h"
...@@ -371,26 +372,67 @@ NsCharToJavaChar(unichar nsChar, NSUInteger modifiers) ...@@ -371,26 +372,67 @@ NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
return nsChar; return nsChar;
} }
static unichar NsGetDeadKeyChar(unsigned short keyCode)
{
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
// Carbon modifiers should be used instead of NSEvent modifiers
UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF;
if (keyboardLayout) {
UInt32 deadKeyState = 0;
UniCharCount maxStringLength = 255;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];
// get the deadKeyState
OSStatus status = UCKeyTranslate(keyboardLayout,
keyCode, kUCKeyActionDown, modifierKeyState,
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
if (status == noErr && deadKeyState != 0) {
// Press SPACE to get the dead key char
status = UCKeyTranslate(keyboardLayout,
kVK_Space, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
if (status == noErr && actualStringLength > 0) {
return unicodeString[0];
}
}
}
return 0;
}
/* /*
* This is the function that uses the table above to take incoming * This is the function that uses the table above to take incoming
* NSEvent keyCodes and translate to the Java virtual key code. * NSEvent keyCodes and translate to the Java virtual key code.
*/ */
static void static void
NsCharToJavaVirtualKeyCode(unichar ch, unichar deadChar, NsCharToJavaVirtualKeyCode(unichar ch, BOOL isDeadChar,
NSUInteger flags, unsigned short key, NSUInteger flags, unsigned short key,
jint *keyCode, jint *keyLocation, BOOL *postsTyped) jint *keyCode, jint *keyLocation, BOOL *postsTyped, unichar *deadChar)
{ {
static size_t size = sizeof(keyTable) / sizeof(struct _key); static size_t size = sizeof(keyTable) / sizeof(struct _key);
NSInteger offset; NSInteger offset;
if (deadChar) { if (isDeadChar) {
unichar testDeadChar = NsGetDeadKeyChar(key);
const struct CharToVKEntry *map; const struct CharToVKEntry *map;
for (map = charToDeadVKTable; map->c != 0; ++map) { for (map = charToDeadVKTable; map->c != 0; ++map) {
if (deadChar == map->c) { if (testDeadChar == map->c) {
*keyCode = map->javaKey; *keyCode = map->javaKey;
*postsTyped = NO; *postsTyped = NO;
// TODO: use UNKNOWN here? // TODO: use UNKNOWN here?
*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
*deadChar = testDeadChar;
return; return;
} }
} }
...@@ -615,20 +657,22 @@ JNF_COCOA_ENTER(env); ...@@ -615,20 +657,22 @@ JNF_COCOA_ENTER(env);
// in = [testChar, testDeadChar, modifierFlags, keyCode] // in = [testChar, testDeadChar, modifierFlags, keyCode]
jchar testChar = (jchar)data[0]; jchar testChar = (jchar)data[0];
jchar testDeadChar = (jchar)data[1]; BOOL isDeadChar = (data[1] != 0);
jint modifierFlags = data[2]; jint modifierFlags = data[2];
jshort keyCode = (jshort)data[3]; jshort keyCode = (jshort)data[3];
jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
jchar testDeadChar = 0;
NsCharToJavaVirtualKeyCode((unichar)testChar, (unichar)testDeadChar, NsCharToJavaVirtualKeyCode((unichar)testChar, isDeadChar,
(NSUInteger)modifierFlags, (unsigned short)keyCode, (NSUInteger)modifierFlags, (unsigned short)keyCode,
&jkeyCode, &jkeyLocation, &postsTyped); &jkeyCode, &jkeyLocation, &postsTyped, &testDeadChar);
// out = [jkeyCode, jkeyLocation]; // out = [jkeyCode, jkeyLocation];
(*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode); (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
(*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation); (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
(*env)->SetIntArrayRegion(env, outData, 2, 1, (jint *)&testDeadChar);
(*env)->ReleaseIntArrayElements(env, inData, data, 0); (*env)->ReleaseIntArrayElements(env, inData, data, 0);
...@@ -685,12 +729,12 @@ Java_sun_lwawt_macosx_event_NSEvent_nsToJavaChar ...@@ -685,12 +729,12 @@ Java_sun_lwawt_macosx_event_NSEvent_nsToJavaChar
(JNIEnv *env, jclass cls, char nsChar, jint modifierFlags) (JNIEnv *env, jclass cls, char nsChar, jint modifierFlags)
{ {
jchar javaChar = 0; jchar javaChar = 0;
JNF_COCOA_ENTER(env); JNF_COCOA_ENTER(env);
javaChar = NsCharToJavaChar(nsChar, modifierFlags); javaChar = NsCharToJavaChar(nsChar, modifierFlags);
JNF_COCOA_EXIT(env); JNF_COCOA_EXIT(env);
return javaChar; return javaChar;
} }
/*
* 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 7196547
* @summary Dead Key implementation for KeyEvent on Mac OS X
* @author alexandr.scherbatiy area=awt.event
* @run main deadKeyMacOSX
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.event.KeyEvent;
import sun.awt.OSInfo;
import sun.awt.SunToolkit;
public class deadKeyMacOSX {
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);
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();
panel.addKeyListener(new DeadKeyListener());
frame.add(panel);
frame.setVisible(true);
toolkit.realSync();
panel.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;
case 2:
if (keyCode != KeyEvent.VK_A) {
throw new RuntimeException("A is not pressed.");
}
if (keyChar != 0xE1) {
throw new RuntimeException("A char does not have ACCUTE accent");
}
state++;
break;
default:
throw new RuntimeException("Excessive keyPressed event.");
}
}
@Override
public void keyTyped(KeyEvent e) {
int keyCode = e.getKeyCode();
char keyChar = e.getKeyChar();
if (state == 3) {
if (keyCode != 0) {
throw new RuntimeException("Key code should be undefined.");
}
if (keyChar != 0xE1) {
throw new RuntimeException("A char does not have ACCUTE accent");
}
} else {
throw new RuntimeException("Wron number of keyTyped events.");
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册