@@ -221,6 +221,13 @@ - (void)setAttributedText:(NSAttributedString *)attributedText
221221
222222 textNeedsUpdate = ([self textOf: attributedTextCopy equals: backedTextInputViewTextCopy] == NO );
223223
224+ #if TARGET_OS_OSX // [macOS
225+ // If we are in a language that uses conversion (e.g. Japanese), ignore updates if we have unconverted text.
226+ if ([self .backedTextInputView hasMarkedText ]) {
227+ textNeedsUpdate = NO ;
228+ }
229+ #endif // [macOS
230+
224231 if ((eventLag == 0 || self.backedTextInputView .ghostTextChanging ) && textNeedsUpdate) { // [macOS]
225232#if !TARGET_OS_OSX // [macOS]
226233 UITextRange *selection = self.backedTextInputView .selectedTextRange ;
@@ -229,6 +236,8 @@ - (void)setAttributedText:(NSAttributedString *)attributedText
229236#endif // macOS]
230237 NSAttributedString *oldAttributedText = [self .backedTextInputView.attributedText copy ];
231238 NSInteger oldTextLength = oldAttributedText.string .length ;
239+ NSInteger oldSelectionStart = selection.location ; // [macOS]
240+ NSInteger oldSelectionEnd = selection.location + selection.length ; // [macOS]
232241
233242 // Ghost text changes should not be part of the undo stack
234243 if (!self.backedTextInputView .ghostTextChanging ) {
@@ -238,6 +247,7 @@ - (void)setAttributedText:(NSAttributedString *)attributedText
238247 [self .backedTextInputView.undoManager registerUndoWithTarget: self handler: ^(RCTBaseTextInputView *strongSelf) {
239248 strongSelf.attributedText = oldAttributedTextWithoutGhostText;
240249 [strongSelf textInputDidChange ];
250+ [strongSelf setSelectionStart: oldSelectionStart selectionEnd: oldSelectionEnd]; // [macOS]
241251 }];
242252 }
243253
@@ -315,7 +325,7 @@ - (void)setSelection:(RCTTextSelection *)selection
315325 NSInteger length = end - selection.start ;
316326 NSRange selectedTextRange = NSMakeRange (start, length);
317327#endif // macOS]
318-
328+
319329 NSInteger eventLag = _nativeEventCount - _mostRecentEventCount;
320330 if (eventLag == 0 && !RCTTextSelectionEqual (previousSelectedTextRange, selectedTextRange)) { // [macOS]
321331 [backedTextInputView setSelectedTextRange: selectedTextRange notifyDelegate: NO ];
@@ -341,7 +351,7 @@ - (void)setSelectionStart:(NSInteger)start selectionEnd:(NSInteger)end
341351#else // [macOS
342352 NSInteger startPosition = MIN (start, end);
343353 NSInteger endPosition = MAX (start, end);
344- [self .backedTextInputView setSelectedTextRange: NSMakeRange (startPosition, endPosition - startPosition) notifyDelegate: NO ];
354+ [self .backedTextInputView setSelectedTextRange: NSMakeRange (startPosition, endPosition - startPosition) notifyDelegate: YES ];
345355#endif // macOS]
346356}
347357
@@ -605,7 +615,7 @@ - (void)submitOnKeyDownIfNeeded:(NSEvent *)event
605615 }
606616 }
607617 }
608-
618+
609619 if (shouldSubmit) {
610620 if (_onSubmitEditing) {
611621 _onSubmitEditing (@{});
@@ -706,7 +716,7 @@ - (NSString *)textInputShouldChangeText:(NSString *)text inRange:(NSRange)range
706716 [backedTextInputView setSelectedTextRange: NSMakeRange (range.location + allowedLength, 0 )
707717 notifyDelegate: YES ];
708718#endif // macOS]
709-
719+
710720 [self textInputDidChange ];
711721 }
712722
@@ -761,17 +771,20 @@ - (void)textInputDidChangeSelection
761771{
762772 self.ghostText = nil ; // [macOS]
763773
764- if (!_onSelectionChange || self.backedTextInputView .ghostTextChanging ) { // [macOS]
765- return ;
766- }
774+ // Run this async to match iOS order of events where we get the onChange first and then onSelectionChange.
775+ dispatch_async (dispatch_get_main_queue (), ^{ // [macOS]
776+ if (!_onSelectionChange || self.backedTextInputView .ghostTextChanging ) {
777+ return ;
778+ }
767779
768- RCTTextSelection *selection = self.selection ;
780+ RCTTextSelection *selection = self.selection ;
769781
770- _onSelectionChange (@{
771- @" selection" : @{
772- @" start" : @(selection.start ),
773- @" end" : @(selection.end ),
774- },
782+ _onSelectionChange (@{
783+ @" selection" : @{
784+ @" start" : @(selection.start ),
785+ @" end" : @(selection.end ),
786+ },
787+ });
775788 });
776789}
777790
@@ -834,7 +847,7 @@ - (BOOL)textInputShouldHandlePaste:(__unused id)sender
834847 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard ];
835848 NSPasteboardType fileType = [pasteboard availableTypeFromArray: @[NSFilenamesPboardType , NSPasteboardTypePNG , NSPasteboardTypeTIFF ]];
836849 NSArray <NSPasteboardType >* pastedTypes = ((RCTUITextView*) self.backedTextInputView ).readablePasteboardTypes ;
837-
850+
838851 // If there's a fileType that is of interest, notify JS. Also blocks notifying JS if it's a text paste
839852 if (_onPaste && fileType != nil && [pastedTypes containsObject: fileType]) {
840853 _onPaste ([self dataTransferInfoFromPasteboard: pasteboard]);
0 commit comments