diff options
author | Nikita Tsarev <nikita.tsarev@jetbrains.com> | 2024-05-07 20:41:59 +0200 |
---|---|---|
committer | Nikita Tsarev <nikita.tsarev@jetbrains.com> | 2024-05-10 23:32:25 +0200 |
commit | 1c9e5f52e76d1ffafd44820b9594e279b9482802 (patch) | |
tree | ba2f0b854fac84502dcfff779642ff9c5545fce0 | |
parent | f7c47bf3cfac51b088c8d754f8f087ebb005f6dd (diff) | |
download | JetBrainsRuntime-upstream-jbr17.tar.gz |
JBR-7119: respect replacementRange in IME events on macOSjb17.0.11-b1294upstream-jbr17
4 files changed, 83 insertions, 28 deletions
diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index 8be6485213b..934cdbe25aa 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -515,25 +515,23 @@ public class CInputMethod extends InputMethodAdapter { fCurrentText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, theHighlight, begin, end); } - /* Called from JNI to select the previously typed glyph during press and hold */ - private void selectPreviousGlyph() { - if (fIMContext == null || fAwtFocussedComponent == null) return; // ??? + private void selectRange(int selectionStart, int length) { + if (fIMContext == null || fAwtFocussedComponent == null) { + return; + } + final int selectionEnd = selectionStart + length; try { LWCToolkit.invokeLater(new Runnable() { public void run() { - final int offset = fIMContext.getInsertPositionOffset(); - if (offset < 1) return; // ??? - if (fAwtFocussedComponent instanceof JTextComponent) { - ((JTextComponent) fAwtFocussedComponent).select(offset - 1, offset); + ((JTextComponent) fAwtFocussedComponent).select(selectionStart, selectionEnd); return; } if (fAwtFocussedComponent instanceof TextComponent) { - ((TextComponent) fAwtFocussedComponent).select(offset - 1, offset); + ((TextComponent) fAwtFocussedComponent).select(selectionStart, selectionEnd); return; } - // TODO: Ideally we want to disable press-and-hold in this case } }, fAwtFocussedComponent); } catch (Exception e) { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index f3a7b17439a..bfe3c59b268 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -60,7 +60,6 @@ static unichar lastCtrlCombo; // Uncomment this line to see fprintfs of each InputMethod API being called on this View //#define IM_DEBUG TRUE -//#define EXTRA_DEBUG //#define LOG_KEY_EVENTS static BOOL shouldUsePressAndHold() { @@ -95,7 +94,6 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, i fEnablePressAndHold = shouldUsePressAndHold(); fInPressAndHold = NO; - fPAHNeedsToSelect = NO; mouseIsOver = NO; [self resetTrackingArea]; @@ -365,6 +363,8 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) { fprintf(stderr, "\tmodifierFlags: 0x%08x\n", (unsigned)[event modifierFlags]); TISInputSourceRef is = TISCopyCurrentKeyboardLayoutInputSource(); fprintf(stderr, "\tTISCopyCurrentKeyboardLayoutInputSource: %s\n", is == nil ? "(nil)" : [(NSString*) TISGetInputSourceProperty(is, kTISPropertyInputSourceID) UTF8String]); + fprintf(stderr, "\twillBeHandledByComplexInputMethod: %s\n", [event willBeHandledByComplexInputMethod] ? "true" : "false"); + CFRelease(is); } #endif @@ -376,6 +376,7 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) { fKeyEventsNeeded = YES; NSString *eventCharacters = [event characters]; + unsigned mods = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; if (([event modifierFlags] & NSControlKeyMask) && [eventCharacters length] == 1) { lastCtrlCombo = [eventCharacters characterAtIndex:0]; @@ -395,7 +396,6 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) { fProcessingKeystroke = NO; if (!fInPressAndHold) { fInPressAndHold = YES; - fPAHNeedsToSelect = YES; } else { // Abandon input to reset IM and unblock input after canceling // input accented symbols @@ -1157,7 +1157,9 @@ static jclass jc_CInputMethod = NULL; - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange { #ifdef IM_DEBUG - fprintf(stderr, "AWTView InputMethod Selector Called : [insertText]: %s\n", [aString UTF8String]); + fprintf(stderr, + "AWTView InputMethod Selector Called : [insertText]: %s, replacementRange: location=%lu, length=%lu\n", + [aString UTF8String], replacementRange.location, replacementRange.length); #endif // IM_DEBUG NSMutableString * useString = [self parseString:aString]; @@ -1194,12 +1196,12 @@ static jclass jc_CInputMethod = NULL; JNIEnv *env = [ThreadUtilities getJNIEnv]; GET_CIM_CLASS(); - // We need to select the previous glyph so that it is overwritten. - if (fPAHNeedsToSelect) { - DECLARE_METHOD(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); + + if (replacementRange.length > 0) { + DECLARE_METHOD(jm_selectRange, jc_CInputMethod, "selectRange", "(II)V"); + (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectRange, replacementRange.location, + replacementRange.length); CHECK_EXCEPTION(); - fPAHNeedsToSelect = NO; } if (usingComplexIM) { @@ -1216,7 +1218,6 @@ static jclass jc_CInputMethod = NULL; actualCharacters = [useString copy]; fKeyEventsNeeded = YES; } - fPAHNeedsToSelect = NO; // Abandon input to reset IM and unblock input after entering accented // symbols @@ -1255,7 +1256,9 @@ static jclass jc_CInputMethod = NULL; NSAttributedString *attrString = (isAttributedString ? (NSAttributedString *)aString : nil); NSString *incomingString = (isAttributedString ? [aString string] : aString); #ifdef IM_DEBUG - fprintf(stderr, "AWTView InputMethod Selector Called : [setMarkedText] \"%s\", loc=%lu, length=%lu\n", [incomingString UTF8String], (unsigned long)selectionRange.location, (unsigned long)selectionRange.length); + fprintf(stderr, "AWTView InputMethod Selector Called :[setMarkedText] \"%s\"," + "selectionRange(%lu, %lu), replacementRange(%lu, %lu)\n", [incomingString UTF8String], + selectionRange.location, selectionRange.length, replacementRange.location, replacementRange.length); #endif // IM_DEBUG JNIEnv *env = [ThreadUtilities getJNIEnv]; GET_CIM_CLASS(); @@ -1263,6 +1266,14 @@ static jclass jc_CInputMethod = NULL; DECLARE_METHOD(jm_addAttribute, jc_CInputMethod, "addAttribute", "(ZZII)V"); DECLARE_METHOD(jm_dispatchText, jc_CInputMethod, "dispatchText", "(IIZ)V"); + if (replacementRange.length > 0) { + DECLARE_METHOD(jm_selectRange, jc_CInputMethod, "selectRange", "(II)V"); + (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectRange, replacementRange.location, + replacementRange.length); + CHECK_EXCEPTION(); + } + + // NSInputContext already did the analysis of the TSM event and created attributes indicating // the underlining and color that should be done to the string. We need to look at the underline // style and color to determine what kind of Java hilighting needs to be done. @@ -1298,14 +1309,6 @@ static jclass jc_CInputMethod = NULL; } } - DECLARE_METHOD(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V"); - // We need to select the previous glyph so that it is overwritten. - if (fPAHNeedsToSelect) { - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_selectPreviousGlyph); - CHECK_EXCEPTION(); - fPAHNeedsToSelect = NO; - } - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_dispatchText, selectionRange.location, selectionRange.length, JNI_FALSE); CHECK_EXCEPTION(); diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java index 146fb2e9005..cf5e22d9c9f 100644 --- a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java +++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java @@ -49,6 +49,7 @@ public class InputMethodTest { CtrlShortcutNewWindowTest (new CtrlShortcutNewWindowTest()), DeadKeysTest (new DeadKeysTest()), FocusMoveUncommitedCharactersTest (new FocusMoveUncommitedCharactersTest()), + JapaneseReconvertTest(new JapaneseReconvertTest()), KeyCodesTest (new KeyCodesTest()), NextAppWinKeyTestDead (new NextAppWinKeyTest(true)), NextAppWinKeyTestNormal (new NextAppWinKeyTest(false)), diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/JapaneseReconvertTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/JapaneseReconvertTest.java new file mode 100644 index 00000000000..24bb753a2ff --- /dev/null +++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/JapaneseReconvertTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024 JetBrains s.r.o. + * 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. + */ + +import static java.awt.event.KeyEvent.*; + +/** + * @test + * @summary Regression test for JBR-7119 Converting to Hanja/Kanji on macOS doesn't replace the converted Hangul/Kana symbols + * @modules java.desktop/sun.lwawt.macosx + * @run main InputMethodTest JapaneseReconvertTest + * @requires (jdk.version.major >= 8 & os.family == "mac") + */ + +public class JapaneseReconvertTest implements Runnable { + @Override + public void run() { + InputMethodTest.layout("com.apple.inputmethod.Kotoeri.RomajiTyping.Japanese"); + InputMethodTest.type(VK_N, 0); + InputMethodTest.type(VK_I, 0); + InputMethodTest.type(VK_H, 0); + InputMethodTest.type(VK_O, 0); + InputMethodTest.type(VK_N, 0); + InputMethodTest.type(VK_G, 0); + InputMethodTest.type(VK_O, 0); + InputMethodTest.type(VK_ENTER, 0); + InputMethodTest.expectText("日本語"); + + InputMethodTest.type(VK_R, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); + InputMethodTest.type(VK_ENTER, 0); + InputMethodTest.type(VK_ENTER, 0); + InputMethodTest.expectText("日本語"); + } +} |