diff --git a/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m b/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m index 21edcea83a..2ef323540b 100644 --- a/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m +++ b/Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m @@ -91,14 +91,29 @@ -(BOOL)ignoreEvent:(UITouch*)touch { // We DO NOT want to process touches from popovers like datepickers and openGallery. // See the OpenGalleryTest2793 sample to test events for openGallery. UIView *v = ctrl.view; - + // Sometimes we receive an event from a view that has already been removed from // the view hierarchy. The call to [pressedView isDescendantOfView:xxx] will throw // a EXC_BAD_ACCESS in this case, so we need to test for this case. BOOL viewInWindow = pressedView != nil && [pressedView window] != nil; - + BOOL ignore = (touch == nil || pressedView == nil || !viewInWindow || ![pressedView isDescendantOfView:v]); + // Touches that land on the active native text editor (the CN1UITextField / + // CN1UITextView created by editStringAtImpl) must be left to UIKit. They + // drive cursor positioning, selection handles, the magnifier loupe, and on + // iOS 26.x the RTI / emoji-search input session. If we dispatch them into + // CN1's pointer pipeline, touchesEnded fires foldKeyboard -- whose + // 22pt-tall hit-test rect rejects most taps on a single-line TextField -- + // which calls stringEdit(YES,...), tears down editingComponent, and lets + // the same touch's pointerReleasedC re-enter Java's TextArea.pointerReleased, + // which recreates the field. The visible symptom is the keyboard bouncing + // and the selection / cursor resetting on every interaction; see #5010. + if (!ignore && editingComponent != nil && pressedView != nil + && [pressedView isDescendantOfView:editingComponent]) { + ignore = YES; + } + return ignore; } @@ -214,7 +229,7 @@ - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - + [super touchesEnded:touches withEvent:event]; if(skipNextTouch) { skipNextTouch = NO;