Flutter Engine
The Flutter Engine
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}
Definition: copy.py:1

◆ 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}
UITextPosition * start()
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}

◆ 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
Definition: FontMgrTest.cpp:50

◆ 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)
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
int BOOL
Definition: windows_types.h:37

◆ 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}
const uintptr_t id

◆ 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}
SK_API sk_sp< SkSurface > ios(9.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

◆ 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}
NSString * temporarilyDeletedComposedCharacter
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

◆ 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}
SeparatedVector2 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}

◆ 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}
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
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.
1331 self.temporarilyDeletedComposedCharacter = nil;
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}

◆ 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

Definition at line 791 of file FlutterTextInputPlugin.mm.

◆ autofillId

- (NSString *) autofillId
readwritenonatomiccopyimplementation

Definition at line 785 of file FlutterTextInputPlugin.mm.

◆ editableTransform

- (CATransform3D) editableTransform
readnonatomicassignimplementation

Definition at line 786 of file FlutterTextInputPlugin.mm.

◆ editMenuTargetRect

- (CGRect) editMenuTargetRect
readwritenonatomicassignimplementation

Definition at line 797 of file FlutterTextInputPlugin.mm.

◆ markedRect

- (CGRect) markedRect
readwritenonatomicassignimplementation

Definition at line 787 of file FlutterTextInputPlugin.mm.

◆ preventCursorDismissWhenResignFirstResponder

- (BOOL) preventCursorDismissWhenResignFirstResponder
readwritenonatomicassignimplementation

Definition at line 789 of file FlutterTextInputPlugin.mm.

◆ temporarilyDeletedComposedCharacter

- (NSString*) temporarilyDeletedComposedCharacter
readwritenonatomiccopyimplementation

Definition at line 796 of file FlutterTextInputPlugin.mm.

◆ textInputClient

- (int) textInputClient
readwritenonatomicassignimplementation

Definition at line 792 of file FlutterTextInputPlugin.mm.

◆ textInputPlugin

- (FlutterTextInputPlugin*) textInputPlugin
readnonatomicweakimplementation

Definition at line 784 of file FlutterTextInputPlugin.mm.


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