Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Instance Methods | Properties | List of all members
FlutterTextInputView Class Reference
Inheritance diagram for FlutterTextInputView:
FlutterSecureTextInputView FlutterSecureTextInputView FlutterTextInputViewSpy

Instance Methods

(UITextInteraction *_textInteraction) - API_AVAILABLE [implementation]
 
(instancetype) - initWithOwner: [implementation]
 
(UIMenu *) - editMenuInteraction:menuForConfiguration:suggestedActions: [implementation]
 
(void) - editMenuInteraction:willDismissMenuForConfiguration:animator: [implementation]
 
(CGRect) - editMenuInteraction:targetRectForConfiguration: [implementation]
 
(void) - showEditMenuWithTargetRect: [implementation]
 
() - ios [implementation]
 
(void) - configureWithDictionary: [implementation]
 
(UITextContentType) - textContentType [implementation]
 
(UIColor *) - insertionPointColor [implementation]
 
(UIColor *) - selectionBarColor [implementation]
 
(UIColor *) - selectionHighlightColor [implementation]
 
(UIInputViewController *) - inputViewController [implementation]
 
(id< FlutterTextInputDelegate >) - textInputDelegate [implementation]
 
(BOOL- respondsToSelector: [implementation]
 
(void) - setTextInputClient: [implementation]
 
() - ios [implementation]
 
(void) - setTextInputState: [implementation]
 
(void) - touchesBegan:withEvent: [implementation]
 
(void) - touchesMoved:withEvent: [implementation]
 
(void) - touchesEnded:withEvent: [implementation]
 
(void) - touchesCancelled:withEvent: [implementation]
 
(void) - touchesEstimatedPropertiesUpdated: [implementation]
 
(NSRange) - clampSelectionFromBase:extent:forText: [implementation]
 
(NSRange) - clampSelection:forText: [implementation]
 
(BOOL- isVisibleToAutofill [implementation]
 
(void) - setIsVisibleToAutofill: [implementation]
 
(BOOL- isScribbleAvailable [implementation]
 
(void) - scribbleInteractionWillBeginWriting: [implementation]
 
(void) - scribbleInteractionDidFinishWriting: [implementation]
 
(BOOL- scribbleInteraction:shouldBeginAtLocation: [implementation]
 
(BOOL- scribbleInteractionShouldDelayFocus: [implementation]
 
(BOOL- canBecomeFirstResponder [implementation]
 
(BOOL- resignFirstResponder [implementation]
 
(BOOL- canPerformAction:withSender: [implementation]
 
(void) - cut: [implementation]
 
(void) - copy: [implementation]
 
(void) - paste: [implementation]
 
(void) - delete: [implementation]
 
(void) - selectAll: [implementation]
 
(id< UITextInputTokenizer >) - tokenizer [implementation]
 
(UITextRange *) - selectedTextRange [implementation]
 
(void) - setSelectedTextRangeLocal: [implementation]
 
(void) - setSelectedTextRange: [implementation]
 
(id- insertDictationResultPlaceholder [implementation]
 
(void) - removeDictationResultPlaceholder:willInsertResult: [implementation]
 
(NSString *) - textInRange: [implementation]
 
(void) - replaceRangeLocal:withText: [implementation]
 
(void) - replaceRange:withText: [implementation]
 
(BOOL- shouldChangeTextInRange:replacementText: [implementation]
 
(void) - setMarkedText:selectedRange: [implementation]
 
(void) - unmarkText [implementation]
 
(UITextRange *) - textRangeFromPosition:toPosition: [implementation]
 
(NSUInteger) - decrementOffsetPosition: [implementation]
 
(NSUInteger) - incrementOffsetPosition: [implementation]
 
(UITextPosition *) - positionFromPosition:offset: [implementation]
 
(UITextPosition *) - positionFromPosition:inDirection:offset: [implementation]
 
(UITextPosition *) - beginningOfDocument [implementation]
 
(UITextPosition *) - endOfDocument [implementation]
 
(NSComparisonResult) - comparePosition:toPosition: [implementation]
 
(NSInteger) - offsetFromPosition:toPosition: [implementation]
 
(UITextPosition *) - positionWithinRange:farthestInDirection: [implementation]
 
(UITextRange *) - characterRangeByExtendingPosition:inDirection: [implementation]
 
(UITextWritingDirection) - baseWritingDirectionForPosition:inDirection: [implementation]
 
(void) - setBaseWritingDirection:forRange: [implementation]
 
(void) - setMarkedRect: [implementation]
 
(void) - setEditableTransform: [implementation]
 
(CGRect) - localRectFromFrameworkTransform: [implementation]
 
(CGRect) - firstRectForRange: [implementation]
 
(CGRect) - caretRectForPosition: [implementation]
 
(UITextPosition *) - closestPositionToPoint: [implementation]
 
(NSArray *) - selectionRectsForRange: [implementation]
 
(UITextPosition *) - closestPositionToPoint:withinRange: [implementation]
 
(UITextRange *) - characterRangeAtPoint: [implementation]
 
(void) - beginFloatingCursorAtPoint: [implementation]
 
(void) - updateFloatingCursorAtPoint: [implementation]
 
(void) - endFloatingCursor [implementation]
 
(void) - updateEditingState [implementation]
 
(void) - updateEditingStateWithDelta: [implementation]
 
(BOOL- hasText [implementation]
 
(void) - insertText: [implementation]
 
(UITextPlaceholder *) - insertTextPlaceholderWithSize: [implementation]
 
(void) - removeTextPlaceholder: [implementation]
 
(void) - deleteBackward [implementation]
 
(void) - postAccessibilityNotification:target: [implementation]
 
(void) - accessibilityElementDidBecomeFocused [implementation]
 
(BOOL- accessibilityElementsHidden [implementation]
 
(void) - resetScribbleInteractionStatusIfEnding [implementation]
 
(void) - pressesBegan:withEvent: [implementation]
 
(void) - pressesChanged:withEvent: [implementation]
 
(void) - pressesEnded:withEvent: [implementation]
 
(void) - pressesCancelled:withEvent: [implementation]
 

Properties

FlutterTextInputPlugintextInputPlugin [implementation]
 
NSString * autofillId [implementation]
 
CATransform3D editableTransform [implementation]
 
CGRect markedRect [implementation]
 
BOOL preventCursorDismissWhenResignFirstResponder [implementation]
 
BOOL accessibilityEnabled [implementation]
 
int textInputClient [implementation]
 
NSString * temporarilyDeletedComposedCharacter [implementation]
 
CGRect editMenuTargetRect [implementation]
 

Detailed Description

Definition at line 802 of file FlutterTextInputPlugin.mm.

Method Documentation

◆ accessibilityElementDidBecomeFocused

- (void) accessibilityElementDidBecomeFocused
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2231 {
2232 if ([self accessibilityElementIsFocused]) {
2233 // For most of the cases, this flutter text input view should never
2234 // receive the focus. If we do receive the focus, we make the best effort
2235 // to send the focus back to the real text field.
2236 FML_DCHECK(_backingTextInputAccessibilityObject);
2237 [self postAccessibilityNotification:UIAccessibilityScreenChangedNotification
2238 target:_backingTextInputAccessibilityObject];
2239 }
2240}
#define FML_DCHECK(condition)
Definition logging.h:103

◆ accessibilityElementsHidden

- (BOOL) accessibilityElementsHidden
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2242 {
2243 return !_accessibilityEnabled;
2244}

◆ API_AVAILABLE

- (UITextInteraction *_textInteraction) API_AVAILABLE (ios(13.0)) 
implementation

◆ baseWritingDirectionForPosition:inDirection:

- (UITextWritingDirection) baseWritingDirectionForPosition: (UITextPosition*)  position
inDirection: (UITextStorageDirection)  direction 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1583 :(UITextPosition*)position
1584 inDirection:(UITextStorageDirection)direction {
1585 // TODO(cbracken) Add RTL handling.
1586 return UITextWritingDirectionNatural;
1587}

◆ beginFloatingCursorAtPoint:

- (void) beginFloatingCursorAtPoint: (CGPoint)  point
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1998 :(CGPoint)point {
1999 // For "beginFloatingCursorAtPoint" and "updateFloatingCursorAtPoint", "point" is roughly:
2000 //
2001 // CGPoint(
2002 // width >= 0 ? point.x.clamp(boundingBox.left, boundingBox.right) : point.x,
2003 // height >= 0 ? point.y.clamp(boundingBox.top, boundingBox.bottom) : point.y,
2004 // )
2005 // where
2006 // point = keyboardPanGestureRecognizer.translationInView(textInputView) + caretRectForPosition
2007 // boundingBox = self.convertRect(bounds, fromView:textInputView)
2008 // bounds = self._selectionClipRect ?? self.bounds
2009 //
2010 // It seems impossible to use a negative "width" or "height", as the "convertRect"
2011 // call always turns a CGRect's negative dimensions into non-negative values, e.g.,
2012 // (1, 2, -3, -4) would become (-2, -2, 3, 4).
2014 _floatingCursorOffset = point;
2015 [self.textInputDelegate flutterTextInputView:self
2016 updateFloatingCursor:FlutterFloatingCursorDragStateStart
2017 withClient:_textInputClient
2018 withPosition:@{@"X" : @0, @"Y" : @0}];
2019}
bool _isFloatingCursorActive
CGPoint _floatingCursorOffset

◆ beginningOfDocument

- (UITextPosition *) beginningOfDocument
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1507 {
1508 return [FlutterTextPosition positionWithIndex:0 affinity:UITextStorageDirectionForward];
1509}
instancetype positionWithIndex:affinity:(NSUInteger index,[affinity] UITextStorageDirection affinity)

◆ canBecomeFirstResponder

- (BOOL) canBecomeFirstResponder
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1164 {
1165 // Only the currently focused input field can
1166 // become the first responder. This prevents iOS
1167 // from changing focus by itself (the framework
1168 // focus will be out of sync if that happens).
1169 return _textInputClient != 0;
1170}

◆ canPerformAction:withSender:

- (BOOL) canPerformAction: (SEL)  action
withSender: (id sender 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1183 :(SEL)action withSender:(id)sender {
1184 if (action == @selector(paste:)) {
1185 // Forbid pasting images, memojis, or other non-string content.
1186 return [UIPasteboard generalPasteboard].hasStrings;
1187 } else if (action == @selector(copy:) || action == @selector(cut:) ||
1188 action == @selector(delete:)) {
1189 return [self textInRange:_selectedTextRange].length > 0;
1190 }
1191 return [super canPerformAction:action withSender:sender];
1192}
if(end==-1)
Definition copy.py:1
const uintptr_t id

◆ caretRectForPosition:

- (CGRect) caretRectForPosition: (UITextPosition*)  position
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1792 :(UITextPosition*)position {
1793 NSInteger index = ((FlutterTextPosition*)position).index;
1794 UITextStorageDirection affinity = ((FlutterTextPosition*)position).affinity;
1795 // Get the selectionRect of the characters before and after the requested caret position.
1796 NSArray<UITextSelectionRect*>* rects = [self
1797 selectionRectsForRange:[FlutterTextRange
1798 rangeWithNSRange:fml::RangeForCharactersInRange(
1799 self.text,
1800 NSMakeRange(
1801 MAX(0, index - 1),
1802 (index >= (NSInteger)self.text.length)
1803 ? 1
1804 : 2))]];
1805 if (rects.count == 0) {
1806 return CGRectZero;
1807 }
1808 if (index == 0) {
1809 // There is no character before the caret, so this will be the bounds of the character after the
1810 // caret position.
1811 CGRect characterAfterCaret = rects[0].rect;
1812 // Return a zero-width rectangle along the upstream edge of the character after the caret
1813 // position.
1814 if ([rects[0] isKindOfClass:[FlutterTextSelectionRect class]] &&
1815 ((FlutterTextSelectionRect*)rects[0]).isRTL) {
1816 return CGRectMake(characterAfterCaret.origin.x + characterAfterCaret.size.width,
1817 characterAfterCaret.origin.y, 0, characterAfterCaret.size.height);
1818 } else {
1819 return CGRectMake(characterAfterCaret.origin.x, characterAfterCaret.origin.y, 0,
1820 characterAfterCaret.size.height);
1821 }
1822 } else if (rects.count == 2 && affinity == UITextStorageDirectionForward) {
1823 // There are characters before and after the caret, with forward direction affinity.
1824 // It's better to use the character after the caret.
1825 CGRect characterAfterCaret = rects[1].rect;
1826 // Return a zero-width rectangle along the upstream edge of the character after the caret
1827 // position.
1828 if ([rects[1] isKindOfClass:[FlutterTextSelectionRect class]] &&
1829 ((FlutterTextSelectionRect*)rects[1]).isRTL) {
1830 return CGRectMake(characterAfterCaret.origin.x + characterAfterCaret.size.width,
1831 characterAfterCaret.origin.y, 0, characterAfterCaret.size.height);
1832 } else {
1833 return CGRectMake(characterAfterCaret.origin.x, characterAfterCaret.origin.y, 0,
1834 characterAfterCaret.size.height);
1835 }
1836 }
1837
1838 // Covers 2 remaining cases:
1839 // 1. there are characters before and after the caret, with backward direction affinity.
1840 // 2. there is only 1 character before the caret (caret is at the end of text).
1841 // For both cases, return a zero-width rectangle along the downstream edge of the character
1842 // before the caret position.
1843 CGRect characterBeforeCaret = rects[0].rect;
1844 if ([rects[0] isKindOfClass:[FlutterTextSelectionRect class]] &&
1845 ((FlutterTextSelectionRect*)rects[0]).isRTL) {
1846 return CGRectMake(characterBeforeCaret.origin.x, characterBeforeCaret.origin.y, 0,
1847 characterBeforeCaret.size.height);
1848 } else {
1849 return CGRectMake(characterBeforeCaret.origin.x + characterBeforeCaret.size.width,
1850 characterBeforeCaret.origin.y, 0, characterBeforeCaret.size.height);
1851 }
1852}

◆ characterRangeAtPoint:

- (UITextRange *) characterRangeAtPoint: (CGPoint)  point
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1964 :(CGPoint)point {
1965 // TODO(cbracken) Implement.
1966 NSUInteger currentIndex = ((FlutterTextPosition*)_selectedTextRange.start).index;
1967 return [FlutterTextRange rangeWithNSRange:fml::RangeForCharacterAtIndex(self.text, currentIndex)];
1968}
FlutterTextRange * _selectedTextRange

◆ characterRangeByExtendingPosition:inDirection:

- (UITextRange *) characterRangeByExtendingPosition: (UITextPosition*)  position
inDirection: (UITextLayoutDirection)  direction 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1561 :(UITextPosition*)position
1562 inDirection:(UITextLayoutDirection)direction {
1563 NSUInteger positionIndex = ((FlutterTextPosition*)position).index;
1564 NSUInteger startIndex;
1565 NSUInteger endIndex;
1566 switch (direction) {
1567 case UITextLayoutDirectionLeft:
1568 case UITextLayoutDirectionUp:
1569 startIndex = [self decrementOffsetPosition:positionIndex];
1570 endIndex = positionIndex;
1571 break;
1572 case UITextLayoutDirectionRight:
1573 case UITextLayoutDirectionDown:
1574 startIndex = positionIndex;
1575 endIndex = [self incrementOffsetPosition:positionIndex];
1576 break;
1577 }
1578 return [FlutterTextRange rangeWithNSRange:NSMakeRange(startIndex, endIndex - startIndex)];
1579}
instancetype rangeWithNSRange:(NSRange range)

◆ clampSelection:forText:

- (NSRange) clampSelection: (NSRange)  range
forText: (NSString*)  text 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1106 :(NSRange)range forText:(NSString*)text {
1107 NSUInteger start = MIN(MAX(range.location, 0), text.length);
1108 NSUInteger length = MIN(range.length, text.length - start);
1109 return NSMakeRange(start, length);
1110}
size_t length
std::u16string text

◆ clampSelectionFromBase:extent:forText:

- (NSRange) clampSelectionFromBase: (int selectionBase
extent: (int selectionExtent
forText: (NSString*)  text 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1097 :(int)selectionBase
1098 extent:(int)selectionExtent
1099 forText:(NSString*)text {
1100 int loc = MIN(selectionBase, selectionExtent);
1101 int len = ABS(selectionExtent - selectionBase);
1102 return loc < 0 ? NSMakeRange(0, 0)
1103 : [self clampSelection:NSMakeRange(loc, len) forText:self.text];
1104}
Type::kYUV Type::kRGBA() int(0.7 *637)

◆ closestPositionToPoint:

- (UITextPosition *) closestPositionToPoint: (CGPoint)  point
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1854 :(CGPoint)point {
1855 if ([_selectionRects count] == 0) {
1856 NSAssert([_selectedTextRange.start isKindOfClass:[FlutterTextPosition class]],
1857 @"Expected a FlutterTextPosition for position (got %@).",
1858 [_selectedTextRange.start class]);
1859 NSUInteger currentIndex = ((FlutterTextPosition*)_selectedTextRange.start).index;
1860 UITextStorageDirection currentAffinity =
1862 return [FlutterTextPosition positionWithIndex:currentIndex affinity:currentAffinity];
1863 }
1864
1866 rangeWithNSRange:fml::RangeForCharactersInRange(self.text, NSMakeRange(0, self.text.length))];
1867 return [self closestPositionToPoint:point withinRange:range];
1868}
int count

◆ closestPositionToPoint:withinRange:

- (UITextPosition *) closestPositionToPoint: (CGPoint)  point
withinRange: (UITextRange*)  range 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1909 :(CGPoint)point withinRange:(UITextRange*)range {
1910 NSAssert([range.start isKindOfClass:[FlutterTextPosition class]],
1911 @"Expected a FlutterTextPosition for range.start (got %@).", [range.start class]);
1912 NSAssert([range.end isKindOfClass:[FlutterTextPosition class]],
1913 @"Expected a FlutterTextPosition for range.end (got %@).", [range.end class]);
1914 NSUInteger start = ((FlutterTextPosition*)range.start).index;
1915 NSUInteger end = ((FlutterTextPosition*)range.end).index;
1916
1917 // Selecting text using the floating cursor is not as precise as the pencil.
1918 // Allow further vertical deviation and base more of the decision on horizontal comparison.
1919 CGFloat verticalPrecision = _isFloatingCursorActive ? 10 : 1;
1920
1921 // Find the selectionRect with a leading-center point that is closest to a given point.
1922 BOOL isFirst = YES;
1923 NSUInteger _closestRectIndex = 0;
1924 for (NSUInteger i = 0; i < [_selectionRects count]; i++) {
1925 NSUInteger position = _selectionRects[i].position;
1926 if (position >= start && position <= end) {
1927 if (isFirst ||
1929 point, _selectionRects[i].rect, _selectionRects[i].isRTL,
1930 /*useTrailingBoundaryOfSelectionRect=*/NO, _selectionRects[_closestRectIndex].rect,
1931 _selectionRects[_closestRectIndex].isRTL, verticalPrecision)) {
1932 isFirst = NO;
1933 _closestRectIndex = i;
1934 }
1935 }
1936 }
1937
1938 FlutterTextPosition* closestPosition =
1939 [FlutterTextPosition positionWithIndex:_selectionRects[_closestRectIndex].position
1940 affinity:UITextStorageDirectionForward];
1941
1942 // Check if the far side of the closest rect is a better fit (e.g. tapping end of line)
1943 // Cannot simply check the _closestRectIndex result from the previous for loop due to RTL
1944 // writing direction and the gaps between selectionRects. So we also need to consider
1945 // the adjacent selectionRects to refine _closestRectIndex.
1946 for (NSUInteger i = MAX(0, _closestRectIndex - 1);
1947 i < MIN(_closestRectIndex + 2, [_selectionRects count]); i++) {
1948 NSUInteger position = _selectionRects[i].position + 1;
1949 if (position >= start && position <= end) {
1951 point, _selectionRects[i].rect, _selectionRects[i].isRTL,
1952 /*useTrailingBoundaryOfSelectionRect=*/YES, _selectionRects[_closestRectIndex].rect,
1953 _selectionRects[_closestRectIndex].isRTL, verticalPrecision)) {
1954 // This is an upstream position
1955 closestPosition = [FlutterTextPosition positionWithIndex:position
1956 affinity:UITextStorageDirectionBackward];
1957 }
1958 }
1959 }
1960
1961 return closestPosition;
1962}
glong glong end
static BOOL IsSelectionRectBoundaryCloserToPoint(CGPoint point, CGRect selectionRect, BOOL selectionRectIsRTL, BOOL useTrailingBoundaryOfSelectionRect, CGRect otherSelectionRect, BOOL otherSelectionRectIsRTL, CGFloat verticalPrecision)
int BOOL

◆ comparePosition:toPosition:

- (NSComparisonResult) comparePosition: (UITextPosition*)  position
toPosition: (UITextPosition*)  other 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1516 :(UITextPosition*)position toPosition:(UITextPosition*)other {
1517 NSUInteger positionIndex = ((FlutterTextPosition*)position).index;
1518 NSUInteger otherIndex = ((FlutterTextPosition*)other).index;
1519 if (positionIndex < otherIndex) {
1520 return NSOrderedAscending;
1521 }
1522 if (positionIndex > otherIndex) {
1523 return NSOrderedDescending;
1524 }
1525 UITextStorageDirection positionAffinity = ((FlutterTextPosition*)position).affinity;
1526 UITextStorageDirection otherAffinity = ((FlutterTextPosition*)other).affinity;
1527 if (positionAffinity == otherAffinity) {
1528 return NSOrderedSame;
1529 }
1530 if (positionAffinity == UITextStorageDirectionBackward) {
1531 // positionAffinity points backwards, otherAffinity points forwards
1532 return NSOrderedAscending;
1533 }
1534 // positionAffinity points forwards, otherAffinity points backwards
1535 return NSOrderedDescending;
1536}

◆ configureWithDictionary:

- (void) configureWithDictionary: (NSDictionary*)  configuration
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

901 :(NSDictionary*)configuration {
902 NSDictionary* inputType = configuration[kKeyboardType];
903 NSString* keyboardAppearance = configuration[kKeyboardAppearance];
904 NSDictionary* autofill = configuration[kAutofillProperties];
905
906 self.secureTextEntry = [configuration[kSecureTextEntry] boolValue];
907 self.enableDeltaModel = [configuration[kEnableDeltaModel] boolValue];
908
910 self.keyboardType = ToUIKeyboardType(inputType);
911 self.returnKeyType = ToUIReturnKeyType(configuration[kInputAction]);
912 self.autocapitalizationType = ToUITextAutoCapitalizationType(configuration);
913 _enableInteractiveSelection = [configuration[kEnableInteractiveSelection] boolValue];
914 NSString* smartDashesType = configuration[kSmartDashesType];
915 // This index comes from the SmartDashesType enum in the framework.
916 bool smartDashesIsDisabled = smartDashesType && [smartDashesType isEqualToString:@"0"];
917 self.smartDashesType = smartDashesIsDisabled ? UITextSmartDashesTypeNo : UITextSmartDashesTypeYes;
918 NSString* smartQuotesType = configuration[kSmartQuotesType];
919 // This index comes from the SmartQuotesType enum in the framework.
920 bool smartQuotesIsDisabled = smartQuotesType && [smartQuotesType isEqualToString:@"0"];
921 self.smartQuotesType = smartQuotesIsDisabled ? UITextSmartQuotesTypeNo : UITextSmartQuotesTypeYes;
922 if ([keyboardAppearance isEqualToString:@"Brightness.dark"]) {
923 self.keyboardAppearance = UIKeyboardAppearanceDark;
924 } else if ([keyboardAppearance isEqualToString:@"Brightness.light"]) {
925 self.keyboardAppearance = UIKeyboardAppearanceLight;
926 } else {
927 self.keyboardAppearance = UIKeyboardAppearanceDefault;
928 }
929 NSString* autocorrect = configuration[kAutocorrectionType];
930 bool autocorrectIsDisabled = autocorrect && ![autocorrect boolValue];
931 self.autocorrectionType =
932 autocorrectIsDisabled ? UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault;
933 self.spellCheckingType =
934 autocorrectIsDisabled ? UITextSpellCheckingTypeNo : UITextSpellCheckingTypeDefault;
935 self.autofillId = AutofillIdFromDictionary(configuration);
936 if (autofill == nil) {
937 self.textContentType = @"";
938 } else {
939 self.textContentType = ToUITextContentType(autofill[kAutofillHints]);
940 [self setTextInputState:autofill[kAutofillEditingValue]];
941 NSAssert(_autofillId, @"The autofill configuration must contain an autofill id");
942 }
943 // The input field needs to be visible for the system autofill
944 // to find it.
945 self.isVisibleToAutofill = autofill || _secureTextEntry;
946}
UIKeyboardAppearance keyboardAppearance
static NSString * AutofillIdFromDictionary(NSDictionary *dictionary)
static UITextAutocapitalizationType ToUITextAutoCapitalizationType(NSDictionary *type)
static NSString *const kAutofillHints
bool _enableInteractiveSelection
static BOOL ShouldShowSystemKeyboard(NSDictionary *type)
static UIKeyboardType ToUIKeyboardType(NSDictionary *type)
bool _isSystemKeyboardEnabled
static NSString *const kInputAction
static UIReturnKeyType ToUIReturnKeyType(NSString *inputType)
static UITextContentType ToUITextContentType(NSArray< NSString * > *hints)

◆ copy:

- (void) copy: (id sender
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1201 :(id)sender {
1202 [UIPasteboard generalPasteboard].string = [self textInRange:_selectedTextRange];
1203}

◆ cut:

- (void) cut: (id sender
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1196 :(id)sender {
1197 [UIPasteboard generalPasteboard].string = [self textInRange:_selectedTextRange];
1198 [self replaceRange:_selectedTextRange withText:@""];
1199}

◆ decrementOffsetPosition:

- (NSUInteger) decrementOffsetPosition: (NSUInteger)  position
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1460 :(NSUInteger)position {
1461 return fml::RangeForCharacterAtIndex(self.text, MAX(0, position - 1)).location;
1462}
NSRange RangeForCharacterAtIndex(NSString *text, NSUInteger index)

◆ delete:

- (void) delete: (id sender
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1212 :(id)sender {
1213 [self replaceRange:_selectedTextRange withText:@""];
1214}

◆ deleteBackward

- (void) deleteBackward
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2179 {
2181 _scribbleFocusStatus = FlutterScribbleFocusStatusUnfocused;
2182 [self resetScribbleInteractionStatusIfEnding];
2183
2184 // When deleting Thai vowel, _selectedTextRange has location
2185 // but does not have length, so we have to manually set it.
2186 // In addition, we needed to delete only a part of grapheme cluster
2187 // because it is the expected behavior of Thai input.
2188 // https://github.com/flutter/flutter/issues/24203
2189 // https://github.com/flutter/flutter/issues/21745
2190 // https://github.com/flutter/flutter/issues/39399
2191 //
2192 // This is needed for correct handling of the deletion of Thai vowel input.
2193 // TODO(cbracken): Get a good understanding of expected behavior of Thai
2194 // input and ensure that this is the correct solution.
2195 // https://github.com/flutter/flutter/issues/28962
2196 if (_selectedTextRange.isEmpty && [self hasText]) {
2197 UITextRange* oldSelectedRange = _selectedTextRange;
2198 NSRange oldRange = ((FlutterTextRange*)oldSelectedRange).range;
2199 if (oldRange.location > 0) {
2200 NSRange newRange = NSMakeRange(oldRange.location - 1, 1);
2201
2202 // We should check if the last character is a part of emoji.
2203 // If so, we must delete the entire emoji to prevent the text from being malformed.
2204 NSRange charRange = fml::RangeForCharacterAtIndex(self.text, oldRange.location - 1);
2205 if (IsEmoji(self.text, charRange)) {
2206 newRange = NSMakeRange(charRange.location, oldRange.location - charRange.location);
2207 }
2208
2210 }
2211 }
2212
2214 // Cache the last deleted emoji to use for an iOS bug where the next
2215 // insertion corrupts the emoji characters.
2216 // See: https://github.com/flutter/flutter/issues/111494#issuecomment-1248441346
2217 if (IsEmoji(self.text, _selectedTextRange.range)) {
2218 NSString* deletedText = [self.text substringWithRange:_selectedTextRange.range];
2219 NSRange deleteFirstCharacterRange = fml::RangeForCharacterAtIndex(deletedText, 0);
2220 self.temporarilyDeletedComposedCharacter =
2221 [deletedText substringWithRange:deleteFirstCharacterRange];
2222 }
2223 [self replaceRange:_selectedTextRange withText:@""];
2224 }
2225}
static BOOL IsEmoji(NSString *text, NSRange charRange)
static FLUTTER_ASSERT_ARC const char kTextAffinityDownstream[]
const char * _selectionAffinity

◆ editMenuInteraction:menuForConfiguration:suggestedActions:

- (UIMenu *) editMenuInteraction: (UIEditMenuInteraction*)  interaction
menuForConfiguration: (UIEditMenuConfiguration*)  configuration
suggestedActions: (ios(16.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

871 :(UIEditMenuInteraction*)interaction
872 menuForConfiguration:(UIEditMenuConfiguration*)configuration
873 suggestedActions:(NSArray<UIMenuElement*>*)suggestedActions API_AVAILABLE(ios(16.0)) {
874 return [UIMenu menuWithChildren:suggestedActions];
875}
UITextInteraction *_textInteraction API_AVAILABLE(ios(13.0))

◆ editMenuInteraction:targetRectForConfiguration:

- (CGRect) editMenuInteraction: (UIEditMenuInteraction*)  interaction
targetRectForConfiguration: (ios(16.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

885 :(UIEditMenuInteraction*)interaction
886 targetRectForConfiguration:(UIEditMenuConfiguration*)configuration API_AVAILABLE(ios(16.0)) {
887 return _editMenuTargetRect;
888}

◆ editMenuInteraction:willDismissMenuForConfiguration:animator:

- (void) editMenuInteraction: (UIEditMenuInteraction*)  interaction
willDismissMenuForConfiguration: (UIEditMenuConfiguration*)  configuration
animator: (ios(16.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

877 :(UIEditMenuInteraction*)interaction
878 willDismissMenuForConfiguration:(UIEditMenuConfiguration*)configuration
879 animator:(id<UIEditMenuInteractionAnimating>)animator
880 API_AVAILABLE(ios(16.0)) {
881 [self.textInputDelegate flutterTextInputView:self
882 willDismissEditMenuWithTextInputClient:_textInputClient];
883}

◆ endFloatingCursor

- (void) endFloatingCursor
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2031 {
2033 [self.textInputDelegate flutterTextInputView:self
2034 updateFloatingCursor:FlutterFloatingCursorDragStateEnd
2035 withClient:_textInputClient
2036 withPosition:@{@"X" : @0, @"Y" : @0}];
2037}

◆ endOfDocument

- (UITextPosition *) endOfDocument
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1511 {
1512 return [FlutterTextPosition positionWithIndex:self.text.length
1513 affinity:UITextStorageDirectionBackward];
1514}

◆ firstRectForRange:

- (CGRect) firstRectForRange: (UITextRange*)  range
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1676 :(UITextRange*)range {
1677 NSAssert([range.start isKindOfClass:[FlutterTextPosition class]],
1678 @"Expected a FlutterTextPosition for range.start (got %@).", [range.start class]);
1679 NSAssert([range.end isKindOfClass:[FlutterTextPosition class]],
1680 @"Expected a FlutterTextPosition for range.end (got %@).", [range.end class]);
1681 NSUInteger start = ((FlutterTextPosition*)range.start).index;
1682 NSUInteger end = ((FlutterTextPosition*)range.end).index;
1683 if (_markedTextRange != nil) {
1684 // The candidates view can't be shown if the framework has not sent the
1685 // first caret rect.
1686 if (CGRectEqualToRect(kInvalidFirstRect, _markedRect)) {
1687 return kInvalidFirstRect;
1688 }
1689
1690 if (CGRectEqualToRect(_cachedFirstRect, kInvalidFirstRect)) {
1691 // If the width returned is too small, that means the framework sent us
1692 // the caret rect instead of the marked text rect. Expand it to 0.2 so
1693 // the IME candidates view would show up.
1694 CGRect rect = _markedRect;
1695 if (CGRectIsEmpty(rect)) {
1696 rect = CGRectInset(rect, -0.1, 0);
1697 }
1698 _cachedFirstRect = [self localRectFromFrameworkTransform:rect];
1699 }
1700
1701 UIView* hostView = _textInputPlugin.hostView;
1702 NSAssert(hostView == nil || [self isDescendantOfView:hostView], @"%@ is not a descendant of %@",
1703 self, hostView);
1704 return hostView ? [hostView convertRect:_cachedFirstRect toView:self] : _cachedFirstRect;
1705 }
1706
1707 if (_scribbleInteractionStatus == FlutterScribbleInteractionStatusNone &&
1708 _scribbleFocusStatus == FlutterScribbleFocusStatusUnfocused) {
1709 if (@available(iOS 17.0, *)) {
1710 // Disable auto-correction highlight feature for iOS 17+.
1711 // In iOS 17+, whenever a character is inserted or deleted, the system will always query
1712 // the rect for every single character of the current word.
1713 // GitHub Issue: https://github.com/flutter/flutter/issues/128406
1714 } else {
1715 // This tells the framework to show the highlight for incorrectly spelled word that is
1716 // about to be auto-corrected.
1717 // There is no other UITextInput API that informs about the auto-correction highlight.
1718 // So we simply add the call here as a workaround.
1719 [self.textInputDelegate flutterTextInputView:self
1720 showAutocorrectionPromptRectForStart:start
1721 end:end
1722 withClient:_textInputClient];
1723 }
1724 }
1725
1726 // The iOS 16 system highlight does not repect the height returned by `firstRectForRange`
1727 // API (unlike iOS 17). So we return CGRectZero to hide it (unless if scribble is enabled).
1728 // To support scribble's advanced gestures (e.g. insert a space with a vertical bar),
1729 // at least 1 character's width is required.
1730 if (@available(iOS 17, *)) {
1731 // No-op
1732 } else if (![self isScribbleAvailable]) {
1733 return CGRectZero;
1734 }
1735
1736 NSUInteger first = start;
1737 if (end < start) {
1738 first = end;
1739 }
1740
1741 CGRect startSelectionRect = CGRectNull;
1742 CGRect endSelectionRect = CGRectNull;
1743 // Selection rects from different langauges may have different minY/maxY.
1744 // So we need to iterate through each rects to update minY/maxY.
1745 CGFloat minY = CGFLOAT_MAX;
1746 CGFloat maxY = CGFLOAT_MIN;
1747
1749 rangeWithNSRange:fml::RangeForCharactersInRange(self.text, NSMakeRange(0, self.text.length))];
1750 for (NSUInteger i = 0; i < [_selectionRects count]; i++) {
1751 BOOL startsOnOrBeforeStartOfRange = _selectionRects[i].position <= first;
1752 BOOL isLastSelectionRect = i + 1 == [_selectionRects count];
1753 BOOL endOfTextIsAfterStartOfRange = isLastSelectionRect && textRange.range.length > first;
1754 BOOL nextSelectionRectIsAfterStartOfRange =
1755 !isLastSelectionRect && _selectionRects[i + 1].position > first;
1756 if (startsOnOrBeforeStartOfRange &&
1757 (endOfTextIsAfterStartOfRange || nextSelectionRectIsAfterStartOfRange)) {
1758 // TODO(hellohaunlin): Remove iOS 17 check. The logic should also work for older versions.
1759 if (@available(iOS 17, *)) {
1760 startSelectionRect = _selectionRects[i].rect;
1761 } else {
1762 return _selectionRects[i].rect;
1763 }
1764 }
1765 if (!CGRectIsNull(startSelectionRect)) {
1766 minY = fmin(minY, CGRectGetMinY(_selectionRects[i].rect));
1767 maxY = fmax(maxY, CGRectGetMaxY(_selectionRects[i].rect));
1768 BOOL endsOnOrAfterEndOfRange = _selectionRects[i].position >= end - 1; // end is exclusive
1769 BOOL nextSelectionRectIsOnNextLine =
1770 !isLastSelectionRect &&
1771 // Selection rects from different langauges in 2 lines may overlap with each other.
1772 // A good approximation is to check if the center of next rect is below the bottom of
1773 // current rect.
1774 // TODO(hellohuanlin): Consider passing the line break info from framework.
1775 CGRectGetMidY(_selectionRects[i + 1].rect) > CGRectGetMaxY(_selectionRects[i].rect);
1776 if (endsOnOrAfterEndOfRange || isLastSelectionRect || nextSelectionRectIsOnNextLine) {
1777 endSelectionRect = _selectionRects[i].rect;
1778 break;
1779 }
1780 }
1781 }
1782 if (CGRectIsNull(startSelectionRect) || CGRectIsNull(endSelectionRect)) {
1783 return CGRectZero;
1784 } else {
1785 // fmin/fmax to support both LTR and RTL languages.
1786 CGFloat minX = fmin(CGRectGetMinX(startSelectionRect), CGRectGetMinX(endSelectionRect));
1787 CGFloat maxX = fmax(CGRectGetMaxX(startSelectionRect), CGRectGetMaxX(endSelectionRect));
1788 return CGRectMake(minX, minY, maxX - minX, maxY - minY);
1789 }
1790}
fml::scoped_nsobject< FlutterTextInputPlugin > _textInputPlugin
CGRect _cachedFirstRect
const CGRect kInvalidFirstRect
FlutterScribbleInteractionStatus _scribbleInteractionStatus
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ hasText

- (BOOL) hasText
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2119 {
2120 return self.text.length > 0;
2121}

◆ incrementOffsetPosition:

- (NSUInteger) incrementOffsetPosition: (NSUInteger)  position
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1464 :(NSUInteger)position {
1465 NSRange charRange = fml::RangeForCharacterAtIndex(self.text, position);
1466 return MIN(position + charRange.length, self.text.length);
1467}

◆ initWithOwner:

- (instancetype) initWithOwner: (FlutterTextInputPlugin*)  textInputPlugin
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

823 self = [super initWithFrame:CGRectZero];
824 if (self) {
826 _textInputClient = 0;
828 _preventCursorDismissWhenResignFirstResponder = NO;
829
830 // UITextInput
831 _text = [[NSMutableString alloc] init];
832 _selectedTextRange = [[FlutterTextRange alloc] initWithNSRange:NSMakeRange(0, 0)];
833 _markedRect = kInvalidFirstRect;
835 _scribbleInteractionStatus = FlutterScribbleInteractionStatusNone;
836 _pendingDeltas = [[NSMutableArray alloc] init];
837 // Initialize with the zero matrix which is not
838 // an affine transform.
839 _editableTransform = CATransform3D();
840
841 // UITextInputTraits
842 _autocapitalizationType = UITextAutocapitalizationTypeSentences;
843 _autocorrectionType = UITextAutocorrectionTypeDefault;
844 _spellCheckingType = UITextSpellCheckingTypeDefault;
845 _enablesReturnKeyAutomatically = NO;
846 _keyboardAppearance = UIKeyboardAppearanceDefault;
847 _keyboardType = UIKeyboardTypeDefault;
848 _returnKeyType = UIReturnKeyDone;
849 _secureTextEntry = NO;
850 _enableDeltaModel = NO;
852 _accessibilityEnabled = NO;
853 _smartQuotesType = UITextSmartQuotesTypeYes;
854 _smartDashesType = UITextSmartDashesTypeYes;
855 _selectionRects = [[NSArray alloc] init];
856
857 if (@available(iOS 14.0, *)) {
858 UIScribbleInteraction* interaction = [[UIScribbleInteraction alloc] initWithDelegate:self];
859 [self addInteraction:interaction];
860 }
861 }
862
863 if (@available(iOS 16.0, *)) {
864 _editMenuInteraction = [[UIEditMenuInteraction alloc] initWithDelegate:self];
865 [self addInteraction:_editMenuInteraction];
866 }
867
868 return self;
869}
FlutterTextInputPlugin * textInputPlugin
static const char kTextAffinityUpstream[]
CATransform3D _editableTransform

◆ inputViewController

- (UIInputViewController *) inputViewController
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

974 {
976 return nil;
977 }
978
980 _inputViewController = [[UIInputViewController alloc] init];
981 }
983}
UIInputViewController * _inputViewController

◆ insertDictationResultPlaceholder

- (id) insertDictationResultPlaceholder
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1273 {
1274 return @"";
1275}

◆ insertionPointColor

- (UIColor *) insertionPointColor
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

962 {
963 return [UIColor clearColor];
964}

◆ insertText:

- (void) insertText: (NSString*)  text
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2123 :(NSString*)text {
2124 if (self.temporarilyDeletedComposedCharacter.length > 0 && text.length == 1 && !text.UTF8String &&
2125 [text characterAtIndex:0] == [self.temporarilyDeletedComposedCharacter characterAtIndex:0]) {
2126 // Workaround for https://github.com/flutter/flutter/issues/111494
2127 // TODO(cyanglaz): revert this workaround if when flutter supports a minimum iOS version which
2128 // this bug is fixed by Apple.
2129 text = self.temporarilyDeletedComposedCharacter;
2130 self.temporarilyDeletedComposedCharacter = nil;
2131 }
2132
2133 NSMutableArray<FlutterTextSelectionRect*>* copiedRects =
2134 [[NSMutableArray alloc] initWithCapacity:[_selectionRects count]];
2135 NSAssert([_selectedTextRange.start isKindOfClass:[FlutterTextPosition class]],
2136 @"Expected a FlutterTextPosition for position (got %@).",
2137 [_selectedTextRange.start class]);
2138 NSUInteger insertPosition = ((FlutterTextPosition*)_selectedTextRange.start).index;
2139 for (NSUInteger i = 0; i < [_selectionRects count]; i++) {
2140 NSUInteger rectPosition = _selectionRects[i].position;
2141 if (rectPosition == insertPosition) {
2142 for (NSUInteger j = 0; j <= text.length; j++) {
2143 [copiedRects addObject:[FlutterTextSelectionRect
2144 selectionRectWithRect:_selectionRects[i].rect
2145 position:rectPosition + j
2146 writingDirection:_selectionRects[i].writingDirection]];
2147 }
2148 } else {
2149 if (rectPosition > insertPosition) {
2150 rectPosition = rectPosition + text.length;
2151 }
2152 [copiedRects addObject:[FlutterTextSelectionRect
2153 selectionRectWithRect:_selectionRects[i].rect
2154 position:rectPosition
2155 writingDirection:_selectionRects[i].writingDirection]];
2156 }
2157 }
2158
2159 _scribbleFocusStatus = FlutterScribbleFocusStatusUnfocused;
2160 [self resetScribbleInteractionStatusIfEnding];
2161 self.selectionRects = copiedRects;
2163 [self replaceRange:_selectedTextRange withText:text];
2164}
instancetype selectionRectWithRect:position:writingDirection:(CGRect rect,[position] NSUInteger position,[writingDirection] NSWritingDirection writingDirection)

◆ insertTextPlaceholderWithSize:

- (UITextPlaceholder *) insertTextPlaceholderWithSize: (ios(13.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2166 :(CGSize)size API_AVAILABLE(ios(13.0)) {
2167 [self.textInputDelegate flutterTextInputView:self
2168 insertTextPlaceholderWithSize:size
2169 withClient:_textInputClient];
2170 _hasPlaceholder = YES;
2171 return [[FlutterTextPlaceholder alloc] init];
2172}
BOOL _hasPlaceholder

◆ ios [1/2]

- ios
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1004 {
1005 if (!_textInteraction) {
1006 _textInteraction = [UITextInteraction textInteractionForMode:UITextInteractionModeEditable];
1007 _textInteraction.textInput = self;
1008 }
1009 return _textInteraction;
1010}

◆ ios [2/2]

- ios
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

897 {
898 [self.editMenuInteraction dismissMenu];
899}

◆ isScribbleAvailable

- (BOOL) isScribbleAvailable
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1131 {
1132 if (@available(iOS 14.0, *)) {
1133 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
1134 return YES;
1135 }
1136 }
1137 return NO;
1138}

◆ isVisibleToAutofill

- (BOOL) isVisibleToAutofill
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1112 {
1113 return self.frame.size.width > 0 && self.frame.size.height > 0;
1114}

◆ localRectFromFrameworkTransform:

- (CGRect) localRectFromFrameworkTransform: (CGRect)  incomingRect
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1633 :(CGRect)incomingRect {
1634 CGPoint points[] = {
1635 incomingRect.origin,
1636 CGPointMake(incomingRect.origin.x, incomingRect.origin.y + incomingRect.size.height),
1637 CGPointMake(incomingRect.origin.x + incomingRect.size.width, incomingRect.origin.y),
1638 CGPointMake(incomingRect.origin.x + incomingRect.size.width,
1639 incomingRect.origin.y + incomingRect.size.height)};
1640
1641 CGPoint origin = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX);
1642 CGPoint farthest = CGPointMake(-CGFLOAT_MAX, -CGFLOAT_MAX);
1643
1644 for (int i = 0; i < 4; i++) {
1645 const CGPoint point = points[i];
1646
1647 CGFloat x = _editableTransform.m11 * point.x + _editableTransform.m21 * point.y +
1649 CGFloat y = _editableTransform.m12 * point.x + _editableTransform.m22 * point.y +
1651
1652 const CGFloat w = _editableTransform.m14 * point.x + _editableTransform.m24 * point.y +
1654
1655 if (w == 0.0) {
1656 return kInvalidFirstRect;
1657 } else if (w != 1.0) {
1658 x /= w;
1659 y /= w;
1660 }
1661
1662 origin.x = MIN(origin.x, x);
1663 origin.y = MIN(origin.y, y);
1664 farthest.x = MAX(farthest.x, x);
1665 farthest.y = MAX(farthest.y, y);
1666 }
1667 return CGRectMake(origin.x, origin.y, farthest.x - origin.x, farthest.y - origin.y);
1668}
static const int points[]
double y
double x
SkScalar w

◆ offsetFromPosition:toPosition:

- (NSInteger) offsetFromPosition: (UITextPosition*)  from
toPosition: (UITextPosition*)  toPosition 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1538 :(UITextPosition*)from toPosition:(UITextPosition*)toPosition {
1539 return ((FlutterTextPosition*)toPosition).index - ((FlutterTextPosition*)from).index;
1540}

◆ paste:

- (void) paste: (id sender
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1205 :(id)sender {
1206 NSString* pasteboardString = [UIPasteboard generalPasteboard].string;
1207 if (pasteboardString != nil) {
1208 [self insertText:pasteboardString];
1209 }
1210}

◆ positionFromPosition:inDirection:offset:

- (UITextPosition *) positionFromPosition: (UITextPosition*)  position
inDirection: (UITextLayoutDirection)  direction
offset: (NSInteger)  offset 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1493 :(UITextPosition*)position
1494 inDirection:(UITextLayoutDirection)direction
1495 offset:(NSInteger)offset {
1496 // TODO(cbracken) Add RTL handling.
1497 switch (direction) {
1498 case UITextLayoutDirectionLeft:
1499 case UITextLayoutDirectionUp:
1500 return [self positionFromPosition:position offset:offset * -1];
1501 case UITextLayoutDirectionRight:
1502 case UITextLayoutDirectionDown:
1503 return [self positionFromPosition:position offset:1];
1504 }
1505}
switch(prop_id)
Point offset

◆ positionFromPosition:offset:

- (UITextPosition *) positionFromPosition: (UITextPosition*)  position
offset: (NSInteger)  offset 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1469 :(UITextPosition*)position offset:(NSInteger)offset {
1470 NSUInteger offsetPosition = ((FlutterTextPosition*)position).index;
1471
1472 NSInteger newLocation = (NSInteger)offsetPosition + offset;
1473 if (newLocation < 0 || newLocation > (NSInteger)self.text.length) {
1474 return nil;
1475 }
1476
1477 if (_scribbleInteractionStatus != FlutterScribbleInteractionStatusNone) {
1478 return [FlutterTextPosition positionWithIndex:newLocation];
1479 }
1480
1481 if (offset >= 0) {
1482 for (NSInteger i = 0; i < offset && offsetPosition < self.text.length; ++i) {
1483 offsetPosition = [self incrementOffsetPosition:offsetPosition];
1484 }
1485 } else {
1486 for (NSInteger i = 0; i < ABS(offset) && offsetPosition > 0; ++i) {
1487 offsetPosition = [self decrementOffsetPosition:offsetPosition];
1488 }
1489 }
1490 return [FlutterTextPosition positionWithIndex:offsetPosition];
1491}
instancetype positionWithIndex:(NSUInteger index)

◆ positionWithinRange:farthestInDirection:

- (UITextPosition *) positionWithinRange: (UITextRange*)  range
farthestInDirection: (UITextLayoutDirection)  direction 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1542 :(UITextRange*)range
1543 farthestInDirection:(UITextLayoutDirection)direction {
1544 NSUInteger index;
1545 UITextStorageDirection affinity;
1546 switch (direction) {
1547 case UITextLayoutDirectionLeft:
1548 case UITextLayoutDirectionUp:
1549 index = ((FlutterTextPosition*)range.start).index;
1550 affinity = UITextStorageDirectionForward;
1551 break;
1552 case UITextLayoutDirectionRight:
1553 case UITextLayoutDirectionDown:
1554 index = ((FlutterTextPosition*)range.end).index;
1555 affinity = UITextStorageDirectionBackward;
1556 break;
1557 }
1558 return [FlutterTextPosition positionWithIndex:index affinity:affinity];
1559}

◆ postAccessibilityNotification:target:

- (void) postAccessibilityNotification: (UIAccessibilityNotifications)  notification
target: (id target 
implementation

Reimplemented in FlutterTextInputViewSpy.

Definition at line 817 of file FlutterTextInputPlugin.mm.

2227 :(UIAccessibilityNotifications)notification target:(id)target {
2228 UIAccessibilityPostNotification(notification, target);
2229}
uint32_t * target

◆ pressesBegan:withEvent:

- (void) pressesBegan: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2253 :(NSSet<UIPress*>*)presses
2254 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
2255 [_textInputPlugin.viewController pressesBegan:presses withEvent:event];
2256}
FlKeyEvent * event

◆ pressesCancelled:withEvent:

- (void) pressesCancelled: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2268 :(NSSet<UIPress*>*)presses
2269 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
2270 [_textInputPlugin.viewController pressesCancelled:presses withEvent:event];
2271}

◆ pressesChanged:withEvent:

- (void) pressesChanged: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2258 :(NSSet<UIPress*>*)presses
2259 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
2260 [_textInputPlugin.viewController pressesChanged:presses withEvent:event];
2261}

◆ pressesEnded:withEvent:

- (void) pressesEnded: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2263 :(NSSet<UIPress*>*)presses
2264 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
2265 [_textInputPlugin.viewController pressesEnded:presses withEvent:event];
2266}

◆ removeDictationResultPlaceholder:willInsertResult:

- (void) removeDictationResultPlaceholder: (id placeholder
willInsertResult: (BOOL willInsertResult 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1277 :(id)placeholder willInsertResult:(BOOL)willInsertResult {
1278}

◆ removeTextPlaceholder:

- (void) removeTextPlaceholder: (ios(13.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2174 :(UITextPlaceholder*)textPlaceholder API_AVAILABLE(ios(13.0)) {
2175 _hasPlaceholder = NO;
2176 [self.textInputDelegate flutterTextInputView:self removeTextPlaceholder:_textInputClient];
2177}

◆ replaceRange:withText:

- (void) replaceRange: (UITextRange*)  range
withText: (NSString*)  text 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1311 :(UITextRange*)range withText:(NSString*)text {
1312 NSString* textBeforeChange = [self.text copy];
1313 NSRange replaceRange = ((FlutterTextRange*)range).range;
1314 [self replaceRangeLocal:replaceRange withText:text];
1315 if (_enableDeltaModel) {
1316 NSRange nextReplaceRange = [self clampSelection:replaceRange forText:textBeforeChange];
1317 [self updateEditingStateWithDelta:flutter::TextEditingDelta(
1318 [textBeforeChange UTF8String],
1319 flutter::TextRange(
1320 nextReplaceRange.location,
1321 nextReplaceRange.location + nextReplaceRange.length),
1322 [text UTF8String])];
1323 } else {
1324 [self updateEditingState];
1325 }
1326}

◆ replaceRangeLocal:withText:

- (void) replaceRangeLocal: (NSRange)  range
withText: (NSString*)  text 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1297 :(NSRange)range withText:(NSString*)text {
1298 [self.text replaceCharactersInRange:[self clampSelection:range forText:self.text]
1299 withString:text];
1300
1301 // Adjust the selected range and the marked text range. There's no
1302 // documentation but UITextField always sets markedTextRange to nil,
1303 // and collapses the selection to the end of the new replacement text.
1304 const NSRange newSelectionRange =
1305 [self clampSelection:NSMakeRange(range.location + text.length, 0) forText:self.text];
1306
1307 [self setSelectedTextRangeLocal:[FlutterTextRange rangeWithNSRange:newSelectionRange]];
1308 self.markedTextRange = nil;
1309}

◆ resetScribbleInteractionStatusIfEnding

- (void) resetScribbleInteractionStatusIfEnding
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2246 {
2247 if (_scribbleInteractionStatus == FlutterScribbleInteractionStatusEnding) {
2248 _scribbleInteractionStatus = FlutterScribbleInteractionStatusNone;
2249 }
2250}

◆ resignFirstResponder

- (BOOL) resignFirstResponder
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1172 {
1173 BOOL success = [super resignFirstResponder];
1174 if (success) {
1175 if (!_preventCursorDismissWhenResignFirstResponder) {
1176 [self.textInputDelegate flutterTextInputView:self
1177 didResignFirstResponderWithTextInputClient:_textInputClient];
1178 }
1179 }
1180 return success;
1181}

◆ respondsToSelector:

- (BOOL) respondsToSelector: (SEL)  selector
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

989 :(SEL)selector {
990 if (@available(iOS 17.0, *)) {
991 // See the comment on this method.
992 if (selector == @selector(insertionPointColor)) {
993 return NO;
994 }
995 }
996 return [super respondsToSelector:selector];
997}

◆ scribbleInteraction:shouldBeginAtLocation:

- (BOOL) scribbleInteraction: (UIScribbleInteraction*)  interaction
shouldBeginAtLocation: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1152 :(UIScribbleInteraction*)interaction
1153 shouldBeginAtLocation:(CGPoint)location API_AVAILABLE(ios(14.0)) {
1154 return YES;
1155}

◆ scribbleInteractionDidFinishWriting:

- (void) scribbleInteractionDidFinishWriting: (ios(14.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1146 :(UIScribbleInteraction*)interaction
1147 API_AVAILABLE(ios(14.0)) {
1148 _scribbleInteractionStatus = FlutterScribbleInteractionStatusEnding;
1149 [self.textInputDelegate flutterTextInputViewScribbleInteractionFinished:self];
1150}

◆ scribbleInteractionShouldDelayFocus:

- (BOOL) scribbleInteractionShouldDelayFocus: (ios(14.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1157 :(UIScribbleInteraction*)interaction
1158 API_AVAILABLE(ios(14.0)) {
1159 return NO;
1160}

◆ scribbleInteractionWillBeginWriting:

- (void) scribbleInteractionWillBeginWriting: (ios(14.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1140 :(UIScribbleInteraction*)interaction
1141 API_AVAILABLE(ios(14.0)) {
1142 _scribbleInteractionStatus = FlutterScribbleInteractionStatusStarted;
1143 [self.textInputDelegate flutterTextInputViewScribbleInteractionBegan:self];
1144}

◆ selectAll:

- (void) selectAll: (id sender
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1216 :(id)sender {
1217 [self setSelectedTextRange:[self textRangeFromPosition:[self beginningOfDocument]
1218 toPosition:[self endOfDocument]]];
1219}

◆ selectedTextRange

- (UITextRange *) selectedTextRange
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1230 {
1231 return [_selectedTextRange copy];
1232}

◆ selectionBarColor

- (UIColor *) selectionBarColor
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

966 {
967 return [UIColor clearColor];
968}

◆ selectionHighlightColor

- (UIColor *) selectionHighlightColor
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

970 {
971 return [UIColor clearColor];
972}

◆ selectionRectsForRange:

- (NSArray *) selectionRectsForRange: (UITextRange*)  range
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1870 :(UITextRange*)range {
1871 // At least in the simulator, swapping to the Japanese keyboard crashes the app as this method
1872 // is called immediately with a UITextRange with a UITextPosition rather than FlutterTextPosition
1873 // for the start and end.
1874 if (![range.start isKindOfClass:[FlutterTextPosition class]]) {
1875 return @[];
1876 }
1877 NSAssert([range.start isKindOfClass:[FlutterTextPosition class]],
1878 @"Expected a FlutterTextPosition for range.start (got %@).", [range.start class]);
1879 NSAssert([range.end isKindOfClass:[FlutterTextPosition class]],
1880 @"Expected a FlutterTextPosition for range.end (got %@).", [range.end class]);
1881 NSUInteger start = ((FlutterTextPosition*)range.start).index;
1882 NSUInteger end = ((FlutterTextPosition*)range.end).index;
1883 NSMutableArray* rects = [[NSMutableArray alloc] init];
1884 for (NSUInteger i = 0; i < [_selectionRects count]; i++) {
1885 if (_selectionRects[i].position >= start &&
1886 (_selectionRects[i].position < end ||
1887 (start == end && _selectionRects[i].position <= end))) {
1888 float width = _selectionRects[i].rect.size.width;
1889 if (start == end) {
1890 width = 0;
1891 }
1892 CGRect rect = CGRectMake(_selectionRects[i].rect.origin.x, _selectionRects[i].rect.origin.y,
1893 width, _selectionRects[i].rect.size.height);
1896 position:_selectionRects[i].position
1897 writingDirection:NSWritingDirectionNatural
1898 containsStart:(i == 0)
1899 containsEnd:(i == fml::RangeForCharactersInRange(
1900 self.text, NSMakeRange(0, self.text.length))
1901 .length)
1902 isVertical:NO];
1903 [rects addObject:selectionRect];
1904 }
1905 }
1906 return rects;
1907}
instancetype selectionRectWithRectAndInfo:position:writingDirection:containsStart:containsEnd:isVertical:(CGRect rect,[position] NSUInteger position,[writingDirection] NSWritingDirection writingDirection,[containsStart] BOOL containsStart,[containsEnd] BOOL containsEnd,[isVertical] BOOL isVertical)
int32_t width

◆ setBaseWritingDirection:forRange:

- (void) setBaseWritingDirection: (UITextWritingDirection)  writingDirection
forRange: (UITextRange*)  range 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1589 :(UITextWritingDirection)writingDirection
1590 forRange:(UITextRange*)range {
1591 // TODO(cbracken) Add RTL handling.
1592}

◆ setEditableTransform:

- (void) setEditableTransform: (NSArray*)  matrix
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1604 :(NSArray*)matrix {
1605 CATransform3D* transform = &_editableTransform;
1606
1607 transform->m11 = [matrix[0] doubleValue];
1608 transform->m12 = [matrix[1] doubleValue];
1609 transform->m13 = [matrix[2] doubleValue];
1610 transform->m14 = [matrix[3] doubleValue];
1611
1612 transform->m21 = [matrix[4] doubleValue];
1613 transform->m22 = [matrix[5] doubleValue];
1614 transform->m23 = [matrix[6] doubleValue];
1615 transform->m24 = [matrix[7] doubleValue];
1616
1617 transform->m31 = [matrix[8] doubleValue];
1618 transform->m32 = [matrix[9] doubleValue];
1619 transform->m33 = [matrix[10] doubleValue];
1620 transform->m34 = [matrix[11] doubleValue];
1621
1622 transform->m41 = [matrix[12] doubleValue];
1623 transform->m42 = [matrix[13] doubleValue];
1624 transform->m43 = [matrix[14] doubleValue];
1625 transform->m44 = [matrix[15] doubleValue];
1626
1627 // Invalidate the cache.
1629}
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47

◆ setIsVisibleToAutofill:

- (void) setIsVisibleToAutofill: (BOOL isVisibleToAutofill
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1122 // This probably needs to change (think it is getting overwritten by the updateSizeAndTransform
1123 // stuff for now).
1124 self.frame = isVisibleToAutofill ? CGRectMake(0, 0, 1, 1) : CGRectZero;
1125}

◆ setMarkedRect:

- (void) setMarkedRect: (CGRect)  markedRect
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1596 :(CGRect)markedRect {
1597 _markedRect = markedRect;
1598 // Invalidate the cache.
1600}

◆ setMarkedText:selectedRange:

- (void) setMarkedText: (NSString*)  markedText
selectedRange: (NSRange)  markedSelectedRange 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1388 :(NSString*)markedText selectedRange:(NSRange)markedSelectedRange {
1389 NSString* textBeforeChange = [self.text copy];
1390
1391 if (_scribbleInteractionStatus != FlutterScribbleInteractionStatusNone ||
1392 _scribbleFocusStatus != FlutterScribbleFocusStatusUnfocused) {
1393 return;
1394 }
1395
1396 if (markedText == nil) {
1397 markedText = @"";
1398 }
1399
1400 const FlutterTextRange* currentMarkedTextRange = (FlutterTextRange*)self.markedTextRange;
1401 const NSRange& actualReplacedRange = currentMarkedTextRange && !currentMarkedTextRange.isEmpty
1402 ? currentMarkedTextRange.range
1404 // No need to call replaceRangeLocal as this method always adjusts the
1405 // selected/marked text ranges anyways.
1406 [self.text replaceCharactersInRange:actualReplacedRange withString:markedText];
1407
1408 const NSRange newMarkedRange = NSMakeRange(actualReplacedRange.location, markedText.length);
1409 self.markedTextRange =
1410 newMarkedRange.length > 0 ? [FlutterTextRange rangeWithNSRange:newMarkedRange] : nil;
1411
1412 [self setSelectedTextRangeLocal:
1414 rangeWithNSRange:[self clampSelection:NSMakeRange(markedSelectedRange.location +
1415 newMarkedRange.location,
1416 markedSelectedRange.length)
1417 forText:self.text]]];
1418 if (_enableDeltaModel) {
1419 NSRange nextReplaceRange = [self clampSelection:actualReplacedRange forText:textBeforeChange];
1420 [self updateEditingStateWithDelta:flutter::TextEditingDelta(
1421 [textBeforeChange UTF8String],
1422 flutter::TextRange(
1423 nextReplaceRange.location,
1424 nextReplaceRange.location + nextReplaceRange.length),
1425 [markedText UTF8String])];
1426 } else {
1427 [self updateEditingState];
1428 }
1429}
UITextRange * markedTextRange

◆ setSelectedTextRange:

- (void) setSelectedTextRange: (UITextRange*)  selectedTextRange
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1247 :(UITextRange*)selectedTextRange {
1249 return;
1250 }
1251
1252 [self setSelectedTextRangeLocal:selectedTextRange];
1253
1254 if (_enableDeltaModel) {
1255 [self updateEditingStateWithDelta:flutter::TextEditingDelta([self.text UTF8String])];
1256 } else {
1257 [self updateEditingState];
1258 }
1259
1260 if (_scribbleInteractionStatus != FlutterScribbleInteractionStatusNone ||
1261 _scribbleFocusStatus == FlutterScribbleFocusStatusFocused) {
1262 NSAssert([selectedTextRange isKindOfClass:[FlutterTextRange class]],
1263 @"Expected a FlutterTextRange for range (got %@).", [selectedTextRange class]);
1265 if (flutterTextRange.range.length > 0) {
1266 [self.textInputDelegate flutterTextInputView:self showToolbar:_textInputClient];
1267 }
1268 }
1269
1270 [self resetScribbleInteractionStatusIfEnding];
1271}

◆ setSelectedTextRangeLocal:

- (void) setSelectedTextRangeLocal: (UITextRange*)  selectedTextRange
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1235 :(UITextRange*)selectedTextRange {
1237 if (self.hasText) {
1240 rangeWithNSRange:fml::RangeForCharactersInRange(self.text, flutterTextRange.range)] copy];
1241 } else {
1242 _selectedTextRange = [selectedTextRange copy];
1243 }
1244 }
1245}

◆ setTextInputClient:

- (void) setTextInputClient: (int client
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

999 :(int)client {
1000 _textInputClient = client;
1001 _hasPlaceholder = NO;
1002}

◆ setTextInputState:

- (void) setTextInputState: (NSDictionary*)  state
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1012 :(NSDictionary*)state {
1013 if (@available(iOS 13.0, *)) {
1014 // [UITextInteraction willMoveToView:] sometimes sets the textInput's inputDelegate
1015 // to nil. This is likely a bug in UIKit. In order to inform the keyboard of text
1016 // and selection changes when that happens, add a dummy UITextInteraction to this
1017 // view so it sets a valid inputDelegate that we can call textWillChange et al. on.
1018 // See https://github.com/flutter/engine/pull/32881.
1019 if (!self.inputDelegate && self.isFirstResponder) {
1020 [self addInteraction:self.textInteraction];
1021 }
1022 }
1023
1024 NSString* newText = state[@"text"];
1025 BOOL textChanged = ![self.text isEqualToString:newText];
1026 if (textChanged) {
1027 [self.inputDelegate textWillChange:self];
1028 [self.text setString:newText];
1029 }
1030 NSInteger composingBase = [state[@"composingBase"] intValue];
1031 NSInteger composingExtent = [state[@"composingExtent"] intValue];
1032 NSRange composingRange = [self clampSelection:NSMakeRange(MIN(composingBase, composingExtent),
1033 ABS(composingBase - composingExtent))
1034 forText:self.text];
1035
1036 self.markedTextRange =
1037 composingRange.length > 0 ? [FlutterTextRange rangeWithNSRange:composingRange] : nil;
1038
1039 NSRange selectedRange = [self clampSelectionFromBase:[state[@"selectionBase"] intValue]
1040 extent:[state[@"selectionExtent"] intValue]
1041 forText:self.text];
1042
1043 NSRange oldSelectedRange = [(FlutterTextRange*)self.selectedTextRange range];
1044 if (!NSEqualRanges(selectedRange, oldSelectedRange)) {
1045 [self.inputDelegate selectionWillChange:self];
1046
1047 [self setSelectedTextRangeLocal:[FlutterTextRange rangeWithNSRange:selectedRange]];
1048
1050 if ([state[@"selectionAffinity"] isEqualToString:@(kTextAffinityUpstream)]) {
1052 }
1053 [self.inputDelegate selectionDidChange:self];
1054 }
1055
1056 if (textChanged) {
1057 [self.inputDelegate textDidChange:self];
1058 }
1059
1060 if (@available(iOS 13.0, *)) {
1061 if (_textInteraction) {
1062 [self removeInteraction:_textInteraction];
1063 }
1064 }
1065}
AtkStateType state
id< UITextInputDelegate > inputDelegate

◆ shouldChangeTextInRange:replacementText:

- (BOOL) shouldChangeTextInRange: (UITextRange*)  range
replacementText: (NSString*)  text 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1328 :(UITextRange*)range replacementText:(NSString*)text {
1329 // `temporarilyDeletedComposedCharacter` should only be used during a single text change session.
1330 // So it needs to be cleared at the start of each text editing session.
1332
1333 if (self.returnKeyType == UIReturnKeyDefault && [text isEqualToString:@"\n"]) {
1334 [self.textInputDelegate flutterTextInputView:self
1335 performAction:FlutterTextInputActionNewline
1336 withClient:_textInputClient];
1337 return YES;
1338 }
1339
1340 if ([text isEqualToString:@"\n"]) {
1341 FlutterTextInputAction action;
1342 switch (self.returnKeyType) {
1343 case UIReturnKeyDefault:
1344 action = FlutterTextInputActionUnspecified;
1345 break;
1346 case UIReturnKeyDone:
1347 action = FlutterTextInputActionDone;
1348 break;
1349 case UIReturnKeyGo:
1350 action = FlutterTextInputActionGo;
1351 break;
1352 case UIReturnKeySend:
1353 action = FlutterTextInputActionSend;
1354 break;
1355 case UIReturnKeySearch:
1356 case UIReturnKeyGoogle:
1357 case UIReturnKeyYahoo:
1358 action = FlutterTextInputActionSearch;
1359 break;
1360 case UIReturnKeyNext:
1361 action = FlutterTextInputActionNext;
1362 break;
1363 case UIReturnKeyContinue:
1364 action = FlutterTextInputActionContinue;
1365 break;
1366 case UIReturnKeyJoin:
1367 action = FlutterTextInputActionJoin;
1368 break;
1369 case UIReturnKeyRoute:
1370 action = FlutterTextInputActionRoute;
1371 break;
1372 case UIReturnKeyEmergencyCall:
1373 action = FlutterTextInputActionEmergencyCall;
1374 break;
1375 }
1376
1377 [self.textInputDelegate flutterTextInputView:self
1378 performAction:action
1379 withClient:_textInputClient];
1380 return NO;
1381 }
1382
1383 return YES;
1384}
UIReturnKeyType returnKeyType

◆ showEditMenuWithTargetRect:

- (void) showEditMenuWithTargetRect: (ios(16.0))  API_AVAILABLE
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

890 :(CGRect)targetRect API_AVAILABLE(ios(16.0)) {
891 _editMenuTargetRect = targetRect;
892 UIEditMenuConfiguration* config =
893 [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:CGPointZero];
894 [self.editMenuInteraction presentEditMenuWithConfiguration:config];
895}

◆ textContentType

- (UITextContentType) textContentType
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

948 {
949 return _textContentType;
950}

◆ textInputDelegate

- (id< FlutterTextInputDelegate >) textInputDelegate
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

985 {
986 return _textInputPlugin.textInputDelegate;
987}

◆ textInRange:

- (NSString *) textInRange: (UITextRange*)  range
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1280 :(UITextRange*)range {
1281 if (!range) {
1282 return nil;
1283 }
1284 NSAssert([range isKindOfClass:[FlutterTextRange class]],
1285 @"Expected a FlutterTextRange for range (got %@).", [range class]);
1286 NSRange textRange = ((FlutterTextRange*)range).range;
1287 NSAssert(textRange.location != NSNotFound, @"Expected a valid text range.");
1288 // Sanitize the range to prevent going out of bounds.
1289 NSUInteger location = MIN(textRange.location, self.text.length);
1290 NSUInteger length = MIN(self.text.length - location, textRange.length);
1291 NSRange safeRange = NSMakeRange(location, length);
1292 return [self.text substringWithRange:safeRange];
1293}

◆ textRangeFromPosition:toPosition:

- (UITextRange *) textRangeFromPosition: (UITextPosition*)  fromPosition
toPosition: (UITextPosition*)  toPosition 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1443 :(UITextPosition*)fromPosition
1444 toPosition:(UITextPosition*)toPosition {
1445 NSUInteger fromIndex = ((FlutterTextPosition*)fromPosition).index;
1446 NSUInteger toIndex = ((FlutterTextPosition*)toPosition).index;
1447 if (toIndex >= fromIndex) {
1448 return [FlutterTextRange rangeWithNSRange:NSMakeRange(fromIndex, toIndex - fromIndex)];
1449 } else {
1450 // toIndex can be smaller than fromIndex, because
1451 // UITextInputStringTokenizer does not handle CJK characters
1452 // well in some cases. See:
1453 // https://github.com/flutter/flutter/issues/58750#issuecomment-644469521
1454 // Swap fromPosition and toPosition to match the behavior of native
1455 // UITextViews.
1456 return [FlutterTextRange rangeWithNSRange:NSMakeRange(toIndex, fromIndex - toIndex)];
1457 }
1458}

◆ tokenizer

- (id< UITextInputTokenizer >) tokenizer
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1223 {
1224 if (_tokenizer == nil) {
1225 _tokenizer = [[FlutterTokenizer alloc] initWithTextInput:self];
1226 }
1227 return _tokenizer;
1228}

◆ touchesBegan:withEvent:

- (void) touchesBegan: (NSSet*)  touches
withEvent: (UIEvent*)  event 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1068 :(NSSet*)touches withEvent:(UIEvent*)event {
1069 _scribbleFocusStatus = FlutterScribbleFocusStatusUnfocused;
1070 [self resetScribbleInteractionStatusIfEnding];
1071 [self.viewResponder touchesBegan:touches withEvent:event];
1072}

◆ touchesCancelled:withEvent:

- (void) touchesCancelled: (NSSet*)  touches
withEvent: (UIEvent*)  event 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1082 :(NSSet*)touches withEvent:(UIEvent*)event {
1083 [self.viewResponder touchesCancelled:touches withEvent:event];
1084}
id< FlutterViewResponder > viewResponder

◆ touchesEnded:withEvent:

- (void) touchesEnded: (NSSet*)  touches
withEvent: (UIEvent*)  event 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1078 :(NSSet*)touches withEvent:(UIEvent*)event {
1079 [self.viewResponder touchesEnded:touches withEvent:event];
1080}

◆ touchesEstimatedPropertiesUpdated:

- (void) touchesEstimatedPropertiesUpdated: (NSSet*)  touches
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1086 :(NSSet*)touches {
1087 [self.viewResponder touchesEstimatedPropertiesUpdated:touches];
1088}

◆ touchesMoved:withEvent:

- (void) touchesMoved: (NSSet*)  touches
withEvent: (UIEvent*)  event 
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1074 :(NSSet*)touches withEvent:(UIEvent*)event {
1075 [self.viewResponder touchesMoved:touches withEvent:event];
1076}

◆ unmarkText

- (void) unmarkText
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

1431 {
1432 if (!self.markedTextRange) {
1433 return;
1434 }
1435 self.markedTextRange = nil;
1436 if (_enableDeltaModel) {
1437 [self updateEditingStateWithDelta:flutter::TextEditingDelta([self.text UTF8String])];
1438 } else {
1439 [self updateEditingState];
1440 }
1441}

◆ updateEditingState

- (void) updateEditingState
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2041 {
2042 NSUInteger selectionBase = ((FlutterTextPosition*)_selectedTextRange.start).index;
2043 NSUInteger selectionExtent = ((FlutterTextPosition*)_selectedTextRange.end).index;
2044
2045 // Empty compositing range is represented by the framework's TextRange.empty.
2046 NSInteger composingBase = -1;
2047 NSInteger composingExtent = -1;
2048 if (self.markedTextRange != nil) {
2049 composingBase = ((FlutterTextPosition*)self.markedTextRange.start).index;
2050 composingExtent = ((FlutterTextPosition*)self.markedTextRange.end).index;
2051 }
2052 NSDictionary* state = @{
2053 @"selectionBase" : @(selectionBase),
2054 @"selectionExtent" : @(selectionExtent),
2055 @"selectionAffinity" : @(_selectionAffinity),
2056 @"selectionIsDirectional" : @(false),
2057 @"composingBase" : @(composingBase),
2058 @"composingExtent" : @(composingExtent),
2059 @"text" : [NSString stringWithString:self.text],
2060 };
2061
2062 if (_textInputClient == 0 && _autofillId != nil) {
2063 [self.textInputDelegate flutterTextInputView:self
2064 updateEditingClient:_textInputClient
2065 withState:state
2066 withTag:_autofillId];
2067 } else {
2068 [self.textInputDelegate flutterTextInputView:self
2069 updateEditingClient:_textInputClient
2070 withState:state];
2071 }
2072}

◆ updateEditingStateWithDelta:

- (void) updateEditingStateWithDelta: (flutter::TextEditingDelta delta
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2075 NSUInteger selectionBase = ((FlutterTextPosition*)_selectedTextRange.start).index;
2076 NSUInteger selectionExtent = ((FlutterTextPosition*)_selectedTextRange.end).index;
2077
2078 // Empty compositing range is represented by the framework's TextRange.empty.
2079 NSInteger composingBase = -1;
2080 NSInteger composingExtent = -1;
2081 if (self.markedTextRange != nil) {
2082 composingBase = ((FlutterTextPosition*)self.markedTextRange.start).index;
2083 composingExtent = ((FlutterTextPosition*)self.markedTextRange.end).index;
2084 }
2085
2086 NSDictionary* deltaToFramework = @{
2087 @"oldText" : @(delta.old_text().c_str()),
2088 @"deltaText" : @(delta.delta_text().c_str()),
2089 @"deltaStart" : @(delta.delta_start()),
2090 @"deltaEnd" : @(delta.delta_end()),
2091 @"selectionBase" : @(selectionBase),
2092 @"selectionExtent" : @(selectionExtent),
2093 @"selectionAffinity" : @(_selectionAffinity),
2094 @"selectionIsDirectional" : @(false),
2095 @"composingBase" : @(composingBase),
2096 @"composingExtent" : @(composingExtent),
2097 };
2098
2099 [_pendingDeltas addObject:deltaToFramework];
2100
2101 if (_pendingDeltas.count == 1) {
2102 __weak FlutterTextInputView* weakSelf = self;
2103 dispatch_async(dispatch_get_main_queue(), ^{
2104 __strong FlutterTextInputView* strongSelf = weakSelf;
2105 if (strongSelf && strongSelf.pendingDeltas.count > 0) {
2106 NSDictionary* deltas = @{
2107 @"deltas" : strongSelf.pendingDeltas,
2108 };
2109
2110 [strongSelf.textInputDelegate flutterTextInputView:strongSelf
2111 updateEditingClient:strongSelf->_textInputClient
2112 withDelta:deltas];
2113 [strongSelf.pendingDeltas removeAllObjects];
2114 }
2115 });
2116 }
2117}
A change in the state of an input field.

◆ updateFloatingCursorAtPoint:

- (void) updateFloatingCursorAtPoint: (CGPoint)  point
implementation

Definition at line 817 of file FlutterTextInputPlugin.mm.

2021 :(CGPoint)point {
2022 [self.textInputDelegate flutterTextInputView:self
2023 updateFloatingCursor:FlutterFloatingCursorDragStateUpdate
2024 withClient:_textInputClient
2025 withPosition:@{
2026 @"X" : @(point.x - _floatingCursorOffset.x),
2027 @"Y" : @(point.y - _floatingCursorOffset.y)
2028 }];
2029}

Property Documentation

◆ accessibilityEnabled

- (BOOL) accessibilityEnabled
readwritenonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 791 of file FlutterTextInputPlugin.mm.

◆ autofillId

- (NSString *) autofillId
readwritenonatomiccopyimplementation

Provided by category FlutterTextInputView().

Definition at line 785 of file FlutterTextInputPlugin.mm.

◆ editableTransform

- (CATransform3D) editableTransform
readnonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 786 of file FlutterTextInputPlugin.mm.

◆ editMenuTargetRect

- (CGRect) editMenuTargetRect
readwritenonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 797 of file FlutterTextInputPlugin.mm.

◆ markedRect

- (CGRect) markedRect
readwritenonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 787 of file FlutterTextInputPlugin.mm.

◆ preventCursorDismissWhenResignFirstResponder

- (BOOL) preventCursorDismissWhenResignFirstResponder
readwritenonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 789 of file FlutterTextInputPlugin.mm.

◆ temporarilyDeletedComposedCharacter

- (NSString*) temporarilyDeletedComposedCharacter
readwritenonatomiccopyimplementation

Provided by category FlutterTextInputView().

Definition at line 796 of file FlutterTextInputPlugin.mm.

◆ textInputClient

- (int) textInputClient
readwritenonatomicassignimplementation

Provided by category FlutterTextInputView().

Definition at line 792 of file FlutterTextInputPlugin.mm.

◆ textInputPlugin

- (FlutterTextInputPlugin*) textInputPlugin
readnonatomicweakimplementation

Provided by category FlutterTextInputView().

Definition at line 784 of file FlutterTextInputPlugin.mm.


The documentation for this class was generated from the following file: