JBR-5953 If hieroglyph typing isn't finalised, focusing another component inserts the composed text there

This commit is contained in:
Dmitry Batrak
2023-08-18 13:27:47 +03:00
committed by jbrbot
parent ab008670de
commit c4992bc60b
5 changed files with 36 additions and 33 deletions

View File

@@ -62,6 +62,7 @@ public class AquaCaret extends DefaultCaret
public void deinstall(final JTextComponent c) { public void deinstall(final JTextComponent c) {
c.removePropertyChangeListener(this); c.removePropertyChangeListener(this);
super.deinstall(c); super.deinstall(c);
mFocused = false;
} }
@Override @Override

View File

@@ -51,7 +51,6 @@ public class CInputMethod extends InputMethodAdapter {
private volatile Component fAwtFocussedComponent; private volatile Component fAwtFocussedComponent;
private LWComponentPeer<?, ?> fAwtFocussedComponentPeer; private LWComponentPeer<?, ?> fAwtFocussedComponentPeer;
private boolean isActive; private boolean isActive;
private boolean isTemporarilyDeactivated;
private static Map<TextAttribute, Integer>[] sHighlightStyles; private static Map<TextAttribute, Integer>[] sHighlightStyles;
@@ -236,12 +235,10 @@ public class CInputMethod extends InputMethodAdapter {
*/ */
public void activate() { public void activate() {
isActive = true; isActive = true;
isTemporarilyDeactivated = false;
} }
public void deactivate(boolean isTemporary) { public void deactivate(boolean isTemporary) {
isActive = false; isActive = false;
isTemporarilyDeactivated = isTemporary;
} }
/** /**
@@ -269,7 +266,7 @@ public class CInputMethod extends InputMethodAdapter {
public void removeNotify() { public void removeNotify() {
if (fAwtFocussedComponentPeer != null) { if (fAwtFocussedComponentPeer != null) {
long modelPtr = getNativeViewPtr(fAwtFocussedComponentPeer); long modelPtr = getNativeViewPtr(fAwtFocussedComponentPeer);
nativeEndComposition(modelPtr); nativeEndComposition(modelPtr, fAwtFocussedComponent);
nativeNotifyPeer(modelPtr, null); nativeNotifyPeer(modelPtr, null);
} }
@@ -284,10 +281,10 @@ public class CInputMethod extends InputMethodAdapter {
* to talk to when responding to key events. * to talk to when responding to key events.
*/ */
protected void setAWTFocussedComponent(Component component) { protected void setAWTFocussedComponent(Component component) {
if ((isTemporarilyDeactivated && component == null) || component == fAwtFocussedComponent) { if (component == null || component == fAwtFocussedComponent) {
// Sometimes input happens for the natively unfocused window // Sometimes input happens for the natively unfocused window
// (e.g. in case of system emoji picker), // (e.g. in case of system emoji picker),
// so we don't reset last focused component on temporary focus lost. // so we don't reset last focused component on focus lost.
return; return;
} }
@@ -355,7 +352,7 @@ public class CInputMethod extends InputMethodAdapter {
*/ */
public void endComposition() { public void endComposition() {
if (fAwtFocussedComponentPeer != null) if (fAwtFocussedComponentPeer != null)
nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer)); nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer), fAwtFocussedComponent);
} }
/** /**
@@ -563,18 +560,21 @@ public class CInputMethod extends InputMethodAdapter {
/** /**
* Frequent callbacks from NSTextInput. I think we're supposed to commit it here? * Frequent callbacks from NSTextInput. I think we're supposed to commit it here?
*/ */
private synchronized void unmarkText() { private synchronized void unmarkText(Component component) {
if (fCurrentText == null || fAwtFocussedComponent == null) return; if (component == null) {
component = fAwtFocussedComponent;
}
if (fCurrentText == null || component == null) return;
TextHitInfo theCaret = TextHitInfo.afterOffset(fCurrentTextLength); TextHitInfo theCaret = TextHitInfo.afterOffset(fCurrentTextLength);
TextHitInfo visiblePosition = theCaret; TextHitInfo visiblePosition = theCaret;
InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent, InputMethodEvent event = new InputMethodEvent(component,
InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
fCurrentText.getIterator(), fCurrentText.getIterator(),
fCurrentTextLength, fCurrentTextLength,
theCaret, theCaret,
visiblePosition); visiblePosition);
LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event); LWCToolkit.postEvent(LWCToolkit.targetToAppContext(component), event);
fCurrentText = null; fCurrentText = null;
fCurrentTextAsString = null; fCurrentTextAsString = null;
fCurrentTextLength = 0; fCurrentTextLength = 0;
@@ -807,7 +807,7 @@ public class CInputMethod extends InputMethodAdapter {
// Note that if nativePeer isn't something that normally accepts keystrokes (i.e., a CPanel) // Note that if nativePeer isn't something that normally accepts keystrokes (i.e., a CPanel)
// these calls will be ignored. // these calls will be ignored.
private native void nativeNotifyPeer(long nativePeer, CInputMethod imInstance); private native void nativeNotifyPeer(long nativePeer, CInputMethod imInstance);
private native void nativeEndComposition(long nativePeer); private native void nativeEndComposition(long nativePeer, Component component);
private native void nativeHandleEvent(LWComponentPeer<?, ?> peer, AWTEvent event); private native void nativeHandleEvent(LWComponentPeer<?, ?> peer, AWTEvent event);
// Returns the locale of the active input method. // Returns the locale of the active input method.

View File

@@ -67,6 +67,6 @@
// Input method-related events // Input method-related events
- (void)setInputMethod:(jobject)inputMethod; - (void)setInputMethod:(jobject)inputMethod;
- (void)abandonInput; - (void)abandonInput:(jobject) component;
@end @end

View File

@@ -393,7 +393,7 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) {
case kVK_End: case kVK_End:
// Abandon input to reset IM and unblock input after // Abandon input to reset IM and unblock input after
// canceling input accented symbols // canceling input accented symbols
[self abandonInput]; [self abandonInput:nil];
break; break;
} }
} }
@@ -1157,7 +1157,7 @@ static jclass jc_CInputMethod = NULL;
// Abandon input to reset IM and unblock input after entering accented // Abandon input to reset IM and unblock input after entering accented
// symbols // symbols
[self abandonInput]; [self abandonInput:nil];
} }
+ (void)keyboardInputSourceChanged:(NSNotification *)notification + (void)keyboardInputSourceChanged:(NSNotification *)notification
@@ -1251,7 +1251,11 @@ static jclass jc_CInputMethod = NULL;
} }
} }
- (void) unmarkText - (void) unmarkText {
[self unmarkText:nil];
}
- (void) unmarkText:(jobject) component
{ {
#ifdef IM_DEBUG #ifdef IM_DEBUG
fprintf(stderr, "AWTView InputMethod Selector Called : [unmarkText]\n"); fprintf(stderr, "AWTView InputMethod Selector Called : [unmarkText]\n");
@@ -1264,8 +1268,8 @@ static jclass jc_CInputMethod = NULL;
// unmarkText cancels any input in progress and commits it to the text field. // unmarkText cancels any input in progress and commits it to the text field.
JNIEnv *env = [ThreadUtilities getJNIEnv]; JNIEnv *env = [ThreadUtilities getJNIEnv];
GET_CIM_CLASS(); GET_CIM_CLASS();
DECLARE_METHOD(jm_unmarkText, jc_CInputMethod, "unmarkText", "()V"); DECLARE_METHOD(jm_unmarkText, jc_CInputMethod, "unmarkText", "(Ljava/awt/Component;)V");
(*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText, component);
CHECK_EXCEPTION(); CHECK_EXCEPTION();
} }
@@ -1526,14 +1530,14 @@ static jclass jc_CInputMethod = NULL;
object:nil]; object:nil];
} }
- (void)abandonInput - (void)abandonInput:(jobject) component
{ {
#ifdef IM_DEBUG #ifdef IM_DEBUG
fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n");
#endif // IM_DEBUG #endif // IM_DEBUG
[ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES];
[self unmarkText]; [self unmarkText:component];
} }
/******************************** END NSTextInputClient Protocol ********************************/ /******************************** END NSTextInputClient Protocol ********************************/

View File

@@ -118,13 +118,6 @@ static void initializeInputMethodController() {
[view setInputMethod:inputMethod]; // inputMethod is a GlobalRef or null to disable. [view setInputMethod:inputMethod]; // inputMethod is a GlobalRef or null to disable.
} }
+ (void) _nativeEndComposition:(AWTView *)view {
if (view == nil) return;
[view abandonInput];
}
@end @end
/* /*
@@ -186,16 +179,21 @@ JNI_COCOA_EXIT(env);
/* /*
* Class: sun_lwawt_macosx_CInputMethod * Class: sun_lwawt_macosx_CInputMethod
* Method: nativeEndComposition * Method: nativeEndComposition
* Signature: (J)V * Signature: (JLjava/awt/Component;)V
*/ */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeEndComposition JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeEndComposition
(JNIEnv *env, jobject this, jlong nativePeer) (JNIEnv *env, jobject this, jlong nativePeer, jobject component)
{ {
JNI_COCOA_ENTER(env); JNI_COCOA_ENTER(env);
AWTView *view = (AWTView *)jlong_to_ptr(nativePeer); AWTView *view = (AWTView *)jlong_to_ptr(nativePeer);
if (!view) return;
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){ jobject componentRef = (*env)->NewGlobalRef(env, component);
[CInputMethod _nativeEndComposition:view]; [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
[view abandonInput:componentRef];
if (componentRef) {
JNIEnv *env = [ThreadUtilities getJNIEnv];
(*env)->DeleteGlobalRef(env, componentRef);
}
}]; }];
JNI_COCOA_EXIT(env); JNI_COCOA_EXIT(env);