|
|
|
|
@@ -12,6 +12,8 @@
|
|
|
|
|
#include "flutter/fml/logging.h"
|
|
|
|
|
#include "flutter/fml/platform/darwin/string_range_sanitization.h"
|
|
|
|
|
|
|
|
|
|
FLUTTER_ASSERT_ARC
|
|
|
|
|
|
|
|
|
|
static const char kTextAffinityDownstream[] = "TextAffinity.downstream";
|
|
|
|
|
static const char kTextAffinityUpstream[] = "TextAffinity.upstream";
|
|
|
|
|
// A delay before enabling the accessibility of FlutterTextInputView after
|
|
|
|
|
@@ -477,7 +479,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
@implementation FlutterTextPosition
|
|
|
|
|
|
|
|
|
|
+ (instancetype)positionWithIndex:(NSUInteger)index {
|
|
|
|
|
return [[[FlutterTextPosition alloc] initWithIndex:index] autorelease];
|
|
|
|
|
return [[FlutterTextPosition alloc] initWithIndex:index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithIndex:(NSUInteger)index {
|
|
|
|
|
@@ -495,7 +497,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
@implementation FlutterTextRange
|
|
|
|
|
|
|
|
|
|
+ (instancetype)rangeWithNSRange:(NSRange)range {
|
|
|
|
|
return [[[FlutterTextRange alloc] initWithNSRange:range] autorelease];
|
|
|
|
|
return [[FlutterTextRange alloc] initWithNSRange:range];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithNSRange:(NSRange)range {
|
|
|
|
|
@@ -531,7 +533,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
|
|
|
|
|
@interface FlutterTokenizer ()
|
|
|
|
|
|
|
|
|
|
@property(nonatomic, assign) FlutterTextInputView* textInputView;
|
|
|
|
|
@property(nonatomic, weak) FlutterTextInputView* textInputView;
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@@ -610,21 +612,21 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
containsStart:(BOOL)containsStart
|
|
|
|
|
containsEnd:(BOOL)containsEnd
|
|
|
|
|
isVertical:(BOOL)isVertical {
|
|
|
|
|
return [[[FlutterTextSelectionRect alloc] initWithRectAndInfo:rect
|
|
|
|
|
position:position
|
|
|
|
|
writingDirection:writingDirection
|
|
|
|
|
containsStart:containsStart
|
|
|
|
|
containsEnd:containsEnd
|
|
|
|
|
isVertical:isVertical] autorelease];
|
|
|
|
|
return [[FlutterTextSelectionRect alloc] initWithRectAndInfo:rect
|
|
|
|
|
position:position
|
|
|
|
|
writingDirection:writingDirection
|
|
|
|
|
containsStart:containsStart
|
|
|
|
|
containsEnd:containsEnd
|
|
|
|
|
isVertical:isVertical];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (instancetype)selectionRectWithRect:(CGRect)rect position:(NSUInteger)position {
|
|
|
|
|
return [[[FlutterTextSelectionRect alloc] initWithRectAndInfo:rect
|
|
|
|
|
position:position
|
|
|
|
|
writingDirection:UITextWritingDirectionNatural
|
|
|
|
|
containsStart:NO
|
|
|
|
|
containsEnd:NO
|
|
|
|
|
isVertical:NO] autorelease];
|
|
|
|
|
return [[FlutterTextSelectionRect alloc] initWithRectAndInfo:rect
|
|
|
|
|
position:position
|
|
|
|
|
writingDirection:UITextWritingDirectionNatural
|
|
|
|
|
containsStart:NO
|
|
|
|
|
containsEnd:NO
|
|
|
|
|
isVertical:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithRectAndInfo:(CGRect)rect
|
|
|
|
|
@@ -674,11 +676,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
UITextField* _textField;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
|
[_textField release];
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (UITextField*)textField {
|
|
|
|
|
if (!_textField) {
|
|
|
|
|
_textField = [[UITextField alloc] init];
|
|
|
|
|
@@ -705,12 +702,12 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@interface FlutterTextInputPlugin ()
|
|
|
|
|
@property(nonatomic, readonly) fml::WeakPtr<FlutterTextInputPlugin> weakPtr;
|
|
|
|
|
@property(nonatomic, readonly) id<FlutterTextInputDelegate> textInputDelegate;
|
|
|
|
|
@property(nonatomic, readonly, weak) id<FlutterTextInputDelegate> textInputDelegate;
|
|
|
|
|
@property(nonatomic, readonly) UIView* hostView;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@interface FlutterTextInputView ()
|
|
|
|
|
@property(nonatomic, readonly, weak) FlutterTextInputPlugin* textInputPlugin;
|
|
|
|
|
@property(nonatomic, copy) NSString* autofillId;
|
|
|
|
|
@property(nonatomic, readonly) CATransform3D editableTransform;
|
|
|
|
|
@property(nonatomic, assign) CGRect markedRect;
|
|
|
|
|
@@ -737,10 +734,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
// when the app shows its own in-flutter keyboard.
|
|
|
|
|
bool _isSystemKeyboardEnabled;
|
|
|
|
|
bool _isFloatingCursorActive;
|
|
|
|
|
fml::WeakPtr<FlutterTextInputPlugin> _textInputPlugin;
|
|
|
|
|
// The view has reached end of life, and is no longer
|
|
|
|
|
// allowed to access its textInputDelegate.
|
|
|
|
|
BOOL _decommissioned;
|
|
|
|
|
bool _enableInteractiveSelection;
|
|
|
|
|
UITextInteraction* _textInteraction API_AVAILABLE(ios(13.0));
|
|
|
|
|
}
|
|
|
|
|
@@ -750,7 +743,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
- (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin {
|
|
|
|
|
self = [super initWithFrame:CGRectZero];
|
|
|
|
|
if (self) {
|
|
|
|
|
_textInputPlugin = textInputPlugin.weakPtr;
|
|
|
|
|
_textInputPlugin = textInputPlugin;
|
|
|
|
|
_textInputClient = 0;
|
|
|
|
|
_selectionAffinity = kTextAffinityUpstream;
|
|
|
|
|
|
|
|
|
|
@@ -778,14 +771,12 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
_enableDeltaModel = NO;
|
|
|
|
|
_enableInteractiveSelection = YES;
|
|
|
|
|
_accessibilityEnabled = NO;
|
|
|
|
|
_decommissioned = NO;
|
|
|
|
|
_smartQuotesType = UITextSmartQuotesTypeYes;
|
|
|
|
|
_smartDashesType = UITextSmartDashesTypeYes;
|
|
|
|
|
_selectionRects = [[NSArray alloc] init];
|
|
|
|
|
|
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
|
|
|
UIScribbleInteraction* interaction =
|
|
|
|
|
[[[UIScribbleInteraction alloc] initWithDelegate:self] autorelease];
|
|
|
|
|
UIScribbleInteraction* interaction = [[UIScribbleInteraction alloc] initWithDelegate:self];
|
|
|
|
|
[self addInteraction:interaction];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -794,7 +785,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)configureWithDictionary:(NSDictionary*)configuration {
|
|
|
|
|
NSAssert(!_decommissioned, @"Attempt to reuse a decommissioned view, for %@", configuration);
|
|
|
|
|
NSDictionary* inputType = configuration[kKeyboardType];
|
|
|
|
|
NSString* keyboardAppearance = configuration[kKeyboardAppearance];
|
|
|
|
|
NSDictionary* autofill = configuration[kAutofillProperties];
|
|
|
|
|
@@ -870,37 +860,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<FlutterTextInputDelegate>)textInputDelegate {
|
|
|
|
|
return _textInputPlugin.get().textInputDelegate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Declares that the view has reached end of life, and
|
|
|
|
|
// is no longer allowed to access its textInputDelegate.
|
|
|
|
|
//
|
|
|
|
|
// UIKit may retain this view (even after it's been removed
|
|
|
|
|
// from the view hierarchy) so that it may outlive the plugin/engine,
|
|
|
|
|
// in which case _textInputDelegate will become a dangling pointer.
|
|
|
|
|
|
|
|
|
|
// The text input plugin needs to call decommission when it should
|
|
|
|
|
// not have access to its FlutterTextInputDelegate any more.
|
|
|
|
|
- (void)decommission {
|
|
|
|
|
_decommissioned = YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
|
[_text release];
|
|
|
|
|
[_markedText release];
|
|
|
|
|
[_markedTextRange release];
|
|
|
|
|
[_selectedTextRange release];
|
|
|
|
|
[_tokenizer release];
|
|
|
|
|
[_autofillId release];
|
|
|
|
|
[_inputViewController release];
|
|
|
|
|
[_selectionRects release];
|
|
|
|
|
[_markedTextStyle release];
|
|
|
|
|
[_textContentType release];
|
|
|
|
|
[_textInteraction release];
|
|
|
|
|
[_temporarilyDeletedComposedCharacter release];
|
|
|
|
|
_temporarilyDeletedComposedCharacter = nil;
|
|
|
|
|
[super dealloc];
|
|
|
|
|
return _textInputPlugin.textInputDelegate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)setTextInputClient:(int)client {
|
|
|
|
|
@@ -910,8 +870,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
|
|
|
|
|
- (UITextInteraction*)textInteraction API_AVAILABLE(ios(13.0)) {
|
|
|
|
|
if (!_textInteraction) {
|
|
|
|
|
_textInteraction =
|
|
|
|
|
[[UITextInteraction textInteractionForMode:UITextInteractionModeEditable] retain];
|
|
|
|
|
_textInteraction = [UITextInteraction textInteractionForMode:UITextInteractionModeEditable];
|
|
|
|
|
_textInteraction.textInput = self;
|
|
|
|
|
}
|
|
|
|
|
return _textInteraction;
|
|
|
|
|
@@ -1136,13 +1095,12 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (UITextRange*)selectedTextRange {
|
|
|
|
|
return [[_selectedTextRange copy] autorelease];
|
|
|
|
|
return [_selectedTextRange copy];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Change the range of selected text, without notifying the framework.
|
|
|
|
|
- (void)setSelectedTextRangeLocal:(UITextRange*)selectedTextRange {
|
|
|
|
|
if (_selectedTextRange != selectedTextRange) {
|
|
|
|
|
UITextRange* oldSelectedRange = _selectedTextRange;
|
|
|
|
|
if (self.hasText) {
|
|
|
|
|
FlutterTextRange* flutterTextRange = (FlutterTextRange*)selectedTextRange;
|
|
|
|
|
_selectedTextRange = [[FlutterTextRange
|
|
|
|
|
@@ -1150,7 +1108,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
} else {
|
|
|
|
|
_selectedTextRange = [selectedTextRange copy];
|
|
|
|
|
}
|
|
|
|
|
[oldSelectedRange release];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1227,7 +1184,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)replaceRange:(UITextRange*)range withText:(NSString*)text {
|
|
|
|
|
NSString* textBeforeChange = [[self.text copy] autorelease];
|
|
|
|
|
NSString* textBeforeChange = [self.text copy];
|
|
|
|
|
NSRange replaceRange = ((FlutterTextRange*)range).range;
|
|
|
|
|
[self replaceRangeLocal:replaceRange withText:text];
|
|
|
|
|
if (_enableDeltaModel) {
|
|
|
|
|
@@ -1302,7 +1259,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)setMarkedText:(NSString*)markedText selectedRange:(NSRange)markedSelectedRange {
|
|
|
|
|
NSString* textBeforeChange = [[self.text copy] autorelease];
|
|
|
|
|
NSString* textBeforeChange = [self.text copy];
|
|
|
|
|
NSRange selectedRange = _selectedTextRange.range;
|
|
|
|
|
NSRange markedTextRange = ((FlutterTextRange*)self.markedTextRange).range;
|
|
|
|
|
NSRange actualReplacedRange;
|
|
|
|
|
@@ -1603,7 +1560,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
_cachedFirstRect = [self localRectFromFrameworkTransform:rect];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UIView* hostView = _textInputPlugin.get().hostView;
|
|
|
|
|
UIView* hostView = _textInputPlugin.hostView;
|
|
|
|
|
NSAssert(hostView == nil || [self isDescendantOfView:hostView], @"%@ is not a descendant of %@",
|
|
|
|
|
self, hostView);
|
|
|
|
|
return hostView ? [hostView convertRect:_cachedFirstRect toView:self] : _cachedFirstRect;
|
|
|
|
|
@@ -1684,7 +1641,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
@"Expected a FlutterTextPosition for range.end (got %@).", [range.end class]);
|
|
|
|
|
NSUInteger start = ((FlutterTextPosition*)range.start).index;
|
|
|
|
|
NSUInteger end = ((FlutterTextPosition*)range.end).index;
|
|
|
|
|
NSMutableArray* rects = [[[NSMutableArray alloc] init] autorelease];
|
|
|
|
|
NSMutableArray* rects = [[NSMutableArray alloc] init];
|
|
|
|
|
for (NSUInteger i = 0; i < [_selectionRects count]; i++) {
|
|
|
|
|
if (_selectionRects[i].position >= start && _selectionRects[i].position <= end) {
|
|
|
|
|
float width = _selectionRects[i].rect.size.width;
|
|
|
|
|
@@ -1910,7 +1867,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
_scribbleFocusStatus = FlutterScribbleFocusStatusUnfocused;
|
|
|
|
|
[self resetScribbleInteractionStatusIfEnding];
|
|
|
|
|
self.selectionRects = copiedRects;
|
|
|
|
|
[copiedRects release];
|
|
|
|
|
_selectionAffinity = kTextAffinityDownstream;
|
|
|
|
|
[self replaceRange:_selectedTextRange withText:text];
|
|
|
|
|
}
|
|
|
|
|
@@ -1920,7 +1876,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
insertTextPlaceholderWithSize:size
|
|
|
|
|
withClient:_textInputClient];
|
|
|
|
|
_hasPlaceholder = YES;
|
|
|
|
|
return [[[FlutterTextPlaceholder alloc] init] autorelease];
|
|
|
|
|
return [[FlutterTextPlaceholder alloc] init];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)removeTextPlaceholder:(UITextPlaceholder*)textPlaceholder API_AVAILABLE(ios(13.0)) {
|
|
|
|
|
@@ -1959,7 +1915,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_selectedTextRange = [[FlutterTextRange rangeWithNSRange:newRange] copy];
|
|
|
|
|
[oldSelectedRange release];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2005,22 +1960,22 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
#pragma mark - Key Events Handling
|
|
|
|
|
- (void)pressesBegan:(NSSet<UIPress*>*)presses
|
|
|
|
|
withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
|
|
|
|
|
[_textInputPlugin.get().viewController pressesBegan:presses withEvent:event];
|
|
|
|
|
[_textInputPlugin.viewController pressesBegan:presses withEvent:event];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)pressesChanged:(NSSet<UIPress*>*)presses
|
|
|
|
|
withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
|
|
|
|
|
[_textInputPlugin.get().viewController pressesChanged:presses withEvent:event];
|
|
|
|
|
[_textInputPlugin.viewController pressesChanged:presses withEvent:event];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)pressesEnded:(NSSet<UIPress*>*)presses
|
|
|
|
|
withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
|
|
|
|
|
[_textInputPlugin.get().viewController pressesEnded:presses withEvent:event];
|
|
|
|
|
[_textInputPlugin.viewController pressesEnded:presses withEvent:event];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)pressesCancelled:(NSSet<UIPress*>*)presses
|
|
|
|
|
withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
|
|
|
|
|
[_textInputPlugin.get().viewController pressesCancelled:presses withEvent:event];
|
|
|
|
|
[_textInputPlugin.viewController pressesCancelled:presses withEvent:event];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
@@ -2060,13 +2015,13 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@interface FlutterTimerProxy : NSObject
|
|
|
|
|
@property(nonatomic, assign) FlutterTextInputPlugin* target;
|
|
|
|
|
@property(nonatomic, weak) FlutterTextInputPlugin* target;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation FlutterTimerProxy
|
|
|
|
|
|
|
|
|
|
+ (instancetype)proxyWithTarget:(FlutterTextInputPlugin*)target {
|
|
|
|
|
FlutterTimerProxy* proxy = [[self new] autorelease];
|
|
|
|
|
FlutterTimerProxy* proxy = [[self alloc] init];
|
|
|
|
|
if (proxy) {
|
|
|
|
|
proxy.target = target;
|
|
|
|
|
}
|
|
|
|
|
@@ -2090,8 +2045,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
|
|
|
|
|
@implementation FlutterTextInputPlugin {
|
|
|
|
|
NSTimer* _enableFlutterTextInputViewAccessibilityTimer;
|
|
|
|
|
std::unique_ptr<fml::WeakPtrFactory<FlutterTextInputPlugin>> _weakFactory;
|
|
|
|
|
id<FlutterTextInputDelegate> _textInputDelegate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithDelegate:(id<FlutterTextInputDelegate>)textInputDelegate {
|
|
|
|
|
@@ -2100,7 +2053,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
if (self) {
|
|
|
|
|
// `_textInputDelegate` is a weak reference because it should retain FlutterTextInputPlugin.
|
|
|
|
|
_textInputDelegate = textInputDelegate;
|
|
|
|
|
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterTextInputPlugin>>(self);
|
|
|
|
|
_autofillContext = [[NSMutableDictionary alloc] init];
|
|
|
|
|
_inputHider = [[FlutterTextInputViewAccessibilityHider alloc] init];
|
|
|
|
|
_scribbleElements = [[NSMutableDictionary alloc] init];
|
|
|
|
|
@@ -2110,19 +2062,12 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
|
_weakFactory.reset();
|
|
|
|
|
[self hideTextInput];
|
|
|
|
|
[_activeView release];
|
|
|
|
|
[_inputHider release];
|
|
|
|
|
[_autofillContext release];
|
|
|
|
|
[_scribbleElements release];
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)removeEnableFlutterTextInputViewAccessibilityTimer {
|
|
|
|
|
if (_enableFlutterTextInputViewAccessibilityTimer) {
|
|
|
|
|
[_enableFlutterTextInputViewAccessibilityTimer invalidate];
|
|
|
|
|
[_enableFlutterTextInputViewAccessibilityTimer release];
|
|
|
|
|
_enableFlutterTextInputViewAccessibilityTimer = nil;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -2131,14 +2076,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
return _activeView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<FlutterTextInputDelegate>)textInputDelegate {
|
|
|
|
|
return _textInputDelegate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (fml::WeakPtr<FlutterTextInputPlugin>)weakPtr {
|
|
|
|
|
return _weakFactory->GetWeakPtr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
|
|
|
|
|
NSString* method = call.method;
|
|
|
|
|
id args = call.arguments;
|
|
|
|
|
@@ -2208,7 +2145,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
|
|
|
|
|
- (void)setSelectionRects:(NSArray*)rects {
|
|
|
|
|
NSMutableArray<FlutterTextSelectionRect*>* rectsAsRect =
|
|
|
|
|
[[[NSMutableArray alloc] initWithCapacity:[rects count]] autorelease];
|
|
|
|
|
[[NSMutableArray alloc] initWithCapacity:[rects count]];
|
|
|
|
|
for (NSUInteger i = 0; i < [rects count]; i++) {
|
|
|
|
|
NSArray<NSNumber*>* rect = rects[i];
|
|
|
|
|
[rectsAsRect
|
|
|
|
|
@@ -2242,11 +2179,11 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
// This results in accessibility focus stuck at the FlutterTextInputView.
|
|
|
|
|
if (!_enableFlutterTextInputViewAccessibilityTimer) {
|
|
|
|
|
_enableFlutterTextInputViewAccessibilityTimer =
|
|
|
|
|
[[NSTimer scheduledTimerWithTimeInterval:kUITextInputAccessibilityEnablingDelaySeconds
|
|
|
|
|
target:[FlutterTimerProxy proxyWithTarget:self]
|
|
|
|
|
selector:@selector(enableActiveViewAccessibility)
|
|
|
|
|
userInfo:nil
|
|
|
|
|
repeats:NO] retain];
|
|
|
|
|
[NSTimer scheduledTimerWithTimeInterval:kUITextInputAccessibilityEnablingDelaySeconds
|
|
|
|
|
target:[FlutterTimerProxy proxyWithTarget:self]
|
|
|
|
|
selector:@selector(enableActiveViewAccessibility)
|
|
|
|
|
userInfo:nil
|
|
|
|
|
repeats:NO];
|
|
|
|
|
}
|
|
|
|
|
[_activeView becomeFirstResponder];
|
|
|
|
|
}
|
|
|
|
|
@@ -2353,7 +2290,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
[_autofillContext removeObjectForKey:autofillId];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return [newView autorelease];
|
|
|
|
|
return newView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (FlutterTextInputView*)updateAndShowAutofillViews:(NSArray*)fields
|
|
|
|
|
@@ -2408,7 +2345,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
if (!inputView) {
|
|
|
|
|
inputView =
|
|
|
|
|
needsPasswordAutofill ? [FlutterSecureTextInputView alloc] : [FlutterTextInputView alloc];
|
|
|
|
|
inputView = [[inputView initWithOwner:self] autorelease];
|
|
|
|
|
inputView = [inputView initWithOwner:self];
|
|
|
|
|
[self addToInputParentViewIfNeeded:inputView];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2431,11 +2368,9 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
return _inputHider.subviews;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Decommissions (See the "decommission" method on FlutterTextInputView) and removes
|
|
|
|
|
// every installed input field, unless it's in the current autofill context.
|
|
|
|
|
// Removes every installed input field, unless it's in the current autofill context.
|
|
|
|
|
//
|
|
|
|
|
// The active view will be decommissioned and removed from its superview too, if
|
|
|
|
|
// includeActiveView is YES.
|
|
|
|
|
// The active view will be removed from its superview too, if includeActiveView is YES.
|
|
|
|
|
// When clearText is YES, the text on the input fields will be set to empty before
|
|
|
|
|
// they are removed from the view hierarchy, to avoid triggering autofill save.
|
|
|
|
|
// If delayRemoval is true, removeFromSuperview will be scheduled on the runloop and
|
|
|
|
|
@@ -2454,7 +2389,6 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
if (clearText) {
|
|
|
|
|
[inputView replaceRangeLocal:NSMakeRange(0, inputView.text.length) withText:@""];
|
|
|
|
|
}
|
|
|
|
|
[inputView decommission];
|
|
|
|
|
if (delayRemoval) {
|
|
|
|
|
[inputView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.1];
|
|
|
|
|
} else {
|
|
|
|
|
@@ -2571,7 +2505,7 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
requestElementsInRect:rect
|
|
|
|
|
result:^(id _Nullable result) {
|
|
|
|
|
NSMutableArray<UIScribbleElementIdentifier>* elements =
|
|
|
|
|
[[[NSMutableArray alloc] init] autorelease];
|
|
|
|
|
[[NSMutableArray alloc] init];
|
|
|
|
|
if ([result isKindOfClass:[NSArray class]]) {
|
|
|
|
|
for (NSArray* elementArray in result) {
|
|
|
|
|
[elements addObject:elementArray[0]];
|
|
|
|
|
@@ -2596,8 +2530,8 @@ static BOOL IsSelectionRectCloserToPoint(CGPoint point,
|
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
|
|
|
UIView* parentView = viewResponder.view;
|
|
|
|
|
if (parentView != nil) {
|
|
|
|
|
UIIndirectScribbleInteraction* scribbleInteraction = [[[UIIndirectScribbleInteraction alloc]
|
|
|
|
|
initWithDelegate:(id<UIIndirectScribbleInteractionDelegate>)self] autorelease];
|
|
|
|
|
UIIndirectScribbleInteraction* scribbleInteraction = [[UIIndirectScribbleInteraction alloc]
|
|
|
|
|
initWithDelegate:(id<UIIndirectScribbleInteractionDelegate>)self];
|
|
|
|
|
[parentView addInteraction:scribbleInteraction];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|