Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Instance Methods | Class Methods | Protected Attributes | Properties | List of all members
FlutterTextInputPlugin Class Reference

#include <FlutterTextInputPlugin.h>

Inheritance diagram for FlutterTextInputPlugin:

Instance Methods

(instancetype) - NS_UNAVAILABLE
 
(instancetype) - initWithDelegate:
 
(void) - handleMethodCall:result:
 
(UIView< UITextInput > *) - textInputView
 
(void) - setUpIndirectScribbleInteraction:
 
(void) - resetViewResponder
 
(BOOL- showEditMenu:
 
(ios(16.0) - API_AVAILABLE
 
(instancetype) - initWithViewController:
 
(BOOL- isFirstResponder
 
(BOOL- handleKeyEvent:
 
(void) - handleKeyboardWillShow: [implementation]
 
(void) - dealloc [implementation]
 
(void) - removeEnableFlutterTextInputViewAccessibilityTimer [implementation]
 
(void) - handlePointerUp: [implementation]
 
(void) - dismissKeyboardScreenshot [implementation]
 
(void) - showKeyboardAndRemoveScreenshot [implementation]
 
(void) - handlePointerMove: [implementation]
 
(void) - setKeyboardContainerHeight: [implementation]
 
(void) - hideKeyboardWithoutAnimationAndAvoidCursorDismissUpdate [implementation]
 
(void) - takeKeyboardScreenshotAndDisplay [implementation]
 
(void) - hideEditMenu [implementation]
 
(void) - setEditableSizeAndTransform: [implementation]
 
(void) - updateMarkedRect: [implementation]
 
(void) - setSelectionRects: [implementation]
 
(void) - startLiveTextInput [implementation]
 
(void) - showTextInput [implementation]
 
(void) - enableActiveViewAccessibility [implementation]
 
(void) - hideTextInput [implementation]
 
(void) - triggerAutofillSave: [implementation]
 
(void) - setPlatformViewTextInputClient [implementation]
 
(void) - setTextInputClient:withConfiguration: [implementation]
 
(FlutterTextInputView *) - createInputViewWith: [implementation]
 
(FlutterTextInputView *) - updateAndShowAutofillViews:focusedField:isPasswordRelated: [implementation]
 
(FlutterTextInputView *) - getOrCreateAutofillableView:isPasswordAutofill: [implementation]
 
(UIView *) - hostView [implementation]
 
(NSArray< UIView * > *) - textInputViews [implementation]
 
(void) - cleanUpViewHierarchy:clearText:delayRemoval: [implementation]
 
(void) - changeInputViewsAutofillVisibility: [implementation]
 
(void) - resetAllClientIds [implementation]
 
(void) - addToInputParentViewIfNeeded: [implementation]
 
(void) - setTextInputEditingState: [implementation]
 
(void) - clearTextInputClient [implementation]
 
(void) - updateConfig: [implementation]
 
(BOOL- indirectScribbleInteraction:isElementFocused: [implementation]
 
(void) - indirectScribbleInteraction:focusElementIfNeeded:referencePoint:completion: [implementation]
 
(BOOL- indirectScribbleInteraction:shouldDelayFocusForElement: [implementation]
 
(void) - indirectScribbleInteraction:willBeginWritingInElement: [implementation]
 
(void) - indirectScribbleInteraction:didFinishWritingInElement: [implementation]
 
(CGRect) - indirectScribbleInteraction:frameForElement: [implementation]
 
(void) - indirectScribbleInteraction:requestElementsInRect:completion: [implementation]
 
(BOOL- handlePress: [implementation]
 
(void) - resignAndRemoveFromSuperview [implementation]
 
(void) - setEditableTransform: [implementation]
 
(void) - updateCaretRect: [implementation]
 
(void) - setEditingState: [implementation]
 
(NSDictionary *) - editingState [implementation]
 
(void) - updateEditState [implementation]
 
(void) - updateEditStateWithDelta: [implementation]
 
(void) - updateTextAndSelection [implementation]
 
(NSString *) - textAffinityString [implementation]
 
(void) - keyDown: [implementation]
 
(void) - keyUp: [implementation]
 
(BOOL- performKeyEquivalent: [implementation]
 
(void) - flagsChanged: [implementation]
 
(void) - mouseDown: [implementation]
 
(void) - mouseUp: [implementation]
 
(void) - mouseDragged: [implementation]
 
(void) - rightMouseDown: [implementation]
 
(void) - rightMouseUp: [implementation]
 
(void) - rightMouseDragged: [implementation]
 
(void) - otherMouseDown: [implementation]
 
(void) - otherMouseUp: [implementation]
 
(void) - otherMouseDragged: [implementation]
 
(void) - mouseMoved: [implementation]
 
(void) - scrollWheel: [implementation]
 
(NSTextInputContext *) - inputContext [implementation]
 
(void) - insertTab: [implementation]
 
(void) - insertText:replacementRange: [implementation]
 
(void) - doCommandBySelector: [implementation]
 
(void) - insertNewline: [implementation]
 
(void) - setMarkedText:selectedRange:replacementRange: [implementation]
 
(void) - unmarkText [implementation]
 
(NSRange) - markedRange [implementation]
 
(BOOL- hasMarkedText [implementation]
 
(NSAttributedString *) - attributedSubstringForProposedRange:actualRange: [implementation]
 
(NSArray< NSString * > *) - validAttributesForMarkedText [implementation]
 
(CGRect) - screenRectFromFrameworkTransform: [implementation]
 
(NSRect) - firstRectForCharacterRange:actualRange: [implementation]
 
(NSUInteger) - characterIndexForPoint: [implementation]
 

Class Methods

(instancetype) + NS_UNAVAILABLE
 

Protected Attributes

 : NSObject <FlutterKeySecondaryResponder
 

Properties

UIIndirectScribbleInteractionDelegate UIViewController * viewController
 
id< FlutterIndirectScribbleDelegateindirectScribbleDelegate
 
NSMutableDictionary< UIScribbleElementIdentifier, NSValue * > * scribbleElements
 
FlutterTextFieldclient
 
id< FlutterTextInputDelegatetextInputDelegate [implementation]
 
NSMutableDictionary< NSString *, FlutterTextInputView * > * autofillContext [implementation]
 
FlutterTextInputViewactiveView [implementation]
 
FlutterTextInputViewAccessibilityHiderinputHider [implementation]
 
UIView * inputHider [implementation]
 
id< FlutterViewResponderviewResponder [implementation]
 
UIView * keyboardViewContainer [implementation]
 
UIView * keyboardView [implementation]
 
UIView * cachedFirstResponder [implementation]
 
CGRect keyboardRect [implementation]
 
CGFloat previousPointerYPosition [implementation]
 
CGFloat pointerYVelocity [implementation]
 
NSTextInputContext * textInputContext [implementation]
 
FlutterMethodChannelchannel [implementation]
 
FlutterViewControllerflutterViewController [implementation]
 
BOOL shown [implementation]
 
uint64_t previouslyPressedFlags [implementation]
 
FlutterTextAffinity textAffinity [implementation]
 
NSNumber * clientID [implementation]
 
NSString * inputType [implementation]
 
NSString * inputAction [implementation]
 
BOOL eventProducedOutput [implementation]
 
BOOL enableDeltaModel [implementation]
 
NSMutableArray * pendingSelectors [implementation]
 
NSString * customRunLoopMode [implementation]
 

Detailed Description

A plugin to handle text input.

Responsible for bridging the native macOS text input system with the Flutter framework text editing classes, via system channels.

This is not an FlutterPlugin since it needs access to FlutterViewController internals, so needs to be managed differently.

When accessibility is on, accessibility bridge creates a NSTextField, i.e. FlutterTextField, for every text field in the Flutter. This plugin acts as a field editor for those NSTextField[s].

Definition at line 33 of file FlutterTextInputPlugin.h.

Method Documentation

◆ addToInputParentViewIfNeeded:

- (void) addToInputParentViewIfNeeded: (FlutterTextInputView*)  inputView
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2899 :(FlutterTextInputView*)inputView {
2900 if (![inputView isDescendantOfView:_inputHider]) {
2901 [_inputHider addSubview:inputView];
2902 }
2903
2904 if (_viewController.view == nil) {
2905 // If view controller's view has detached from flutter engine, we don't add _inputHider
2906 // in parent view to fallback and avoid crash.
2907 // https://github.com/flutter/flutter/issues/106404.
2908 return;
2909 }
2910 UIView* parentView = self.hostView;
2911 if (_inputHider.superview != parentView) {
2912 [parentView addSubview:_inputHider];
2913 }
2914}
fml::WeakNSObject< FlutterViewController > _viewController

◆ API_AVAILABLE

- (ios(16.0) API_AVAILABLE

◆ attributedSubstringForProposedRange:actualRange:

- (NSAttributedString *) attributedSubstringForProposedRange: (NSRange)  range
actualRange: (NSRangePointer)  actualRange 
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

898 :(NSRange)range
899 actualRange:(NSRangePointer)actualRange {
900 if (_activeModel == nullptr) {
901 return nil;
902 }
903 if (actualRange != nil) {
904 *actualRange = range;
905 }
906 NSString* text = [NSString stringWithUTF8String:_activeModel->GetText().c_str()];
907 NSString* substring = [text substringWithRange:range];
908 return [[NSAttributedString alloc] initWithString:substring attributes:nil];
909}
if(end==-1)
std::u16string text

◆ changeInputViewsAutofillVisibility:

- (void) changeInputViewsAutofillVisibility: (BOOL newVisibility
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2874 :(BOOL)newVisibility {
2875 for (UIView* view in self.textInputViews) {
2876 if ([view isKindOfClass:[FlutterTextInputView class]]) {
2877 FlutterTextInputView* inputView = (FlutterTextInputView*)view;
2878 inputView.isVisibleToAutofill = newVisibility;
2879 }
2880 }
2881}
NSArray< UIView * > * textInputViews()
int BOOL

◆ characterIndexForPoint:

- (NSUInteger) characterIndexForPoint: (NSPoint)  point
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

968 :(NSPoint)point {
969 // TODO(cbracken): Implement.
970 // Note: This function can't easily be implemented under the system-message architecture.
971 return 0;
972}

◆ cleanUpViewHierarchy:clearText:delayRemoval:

- (void) cleanUpViewHierarchy: (BOOL includeActiveView
clearText: (BOOL clearText
delayRemoval: (BOOL delayRemoval 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2851 :(BOOL)includeActiveView
2852 clearText:(BOOL)clearText
2853 delayRemoval:(BOOL)delayRemoval {
2854 for (UIView* view in self.textInputViews) {
2855 if ([view isKindOfClass:[FlutterTextInputView class]] &&
2856 (includeActiveView || view != _activeView)) {
2857 FlutterTextInputView* inputView = (FlutterTextInputView*)view;
2858 if (_autofillContext[inputView.autofillId] != view) {
2859 if (clearText) {
2860 [inputView replaceRangeLocal:NSMakeRange(0, inputView.text.length) withText:@""];
2861 }
2862 if (delayRemoval) {
2863 [inputView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.1];
2864 } else {
2865 [inputView removeFromSuperview];
2866 }
2867 }
2868 }
2869 }
2870}
void replaceRangeLocal:withText:(NSRange range, [withText] NSString *text)
for(int row=0;row< height;++row)

◆ clearTextInputClient

- (void) clearTextInputClient
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2920 {
2921 [_activeView setTextInputClient:0];
2922 _activeView.frame = CGRectZero;
2923}

◆ createInputViewWith:

- (FlutterTextInputView *) createInputViewWith: (NSDictionary*)  configuration
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2748 :(NSDictionary*)configuration {
2749 NSString* autofillId = AutofillIdFromDictionary(configuration);
2750 if (autofillId) {
2751 [_autofillContext removeObjectForKey:autofillId];
2752 }
2753 FlutterTextInputView* newView = [[FlutterTextInputView alloc] initWithOwner:self];
2754 [newView configureWithDictionary:configuration];
2755 [self addToInputParentViewIfNeeded:newView];
2756
2757 for (NSDictionary* field in configuration[kAssociatedAutofillFields]) {
2758 NSString* autofillId = AutofillIdFromDictionary(field);
2759 if (autofillId && AutofillTypeOf(field) == kFlutterAutofillTypeNone) {
2760 [_autofillContext removeObjectForKey:autofillId];
2761 }
2762 }
2763 return newView;
2764}
void configureWithDictionary:(NSDictionary *configuration)
static NSString * AutofillIdFromDictionary(NSDictionary *dictionary)
static NSString *const kAssociatedAutofillFields
static FlutterAutofillType AutofillTypeOf(NSDictionary *configuration)

◆ dealloc

- (void) dealloc
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2374 {
2375 [self hideTextInput];
2376}

◆ dismissKeyboardScreenshot

- (void) dismissKeyboardScreenshot
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2477 {
2478 for (UIView* subView in _keyboardViewContainer.subviews) {
2479 [subView removeFromSuperview];
2480 }
2481}

◆ doCommandBySelector:

- (void) doCommandBySelector: (SEL)  selector
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

770 :(SEL)selector {
771 _eventProducedOutput |= selector != NSSelectorFromString(@"noop:");
772 if ([self respondsToSelector:selector]) {
773 // Note: The more obvious [self performSelector...] doesn't give ARC enough information to
774 // handle retain semantics properly. See https://stackoverflow.com/questions/7017281/ for more
775 // information.
776 IMP imp = [self methodForSelector:selector];
777 void (*func)(id, SEL, id) = reinterpret_cast<void (*)(id, SEL, id)>(imp);
778 func(self, selector, nil);
779 }
780
781 if (selector == @selector(insertNewline:)) {
782 // Already handled through text insertion (multiline) or action.
783 return;
784 }
785
786 // Group multiple selectors received within a single run loop turn so that
787 // the framework can process them in single microtask.
788 NSString* name = NSStringFromSelector(selector);
789 if (_pendingSelectors == nil) {
790 _pendingSelectors = [NSMutableArray array];
791 }
792 [_pendingSelectors addObject:name];
793
794 if (_pendingSelectors.count == 1) {
795 __weak NSMutableArray* selectors = _pendingSelectors;
797 __weak NSNumber* clientID = self.clientID;
798
799 CFStringRef runLoopMode = self.customRunLoopMode != nil
800 ? (__bridge CFStringRef)self.customRunLoopMode
801 : kCFRunLoopCommonModes;
802
803 CFRunLoopPerformBlock(CFRunLoopGetMain(), runLoopMode, ^{
804 if (selectors.count > 0) {
805 [channel invokeMethod:kPerformSelectors arguments:@[ clientID, selectors ]];
806 [selectors removeAllObjects];
807 }
808 });
809 }
810}
FlutterMethodChannel * _channel
const char * name
Definition fuchsia.cc:50
FlutterMethodChannel * channel
const uintptr_t id

◆ editingState

- (NSDictionary *) editingState
implementation

Provided by category FlutterTextInputPlugin(TestMethods).

Definition at line 339 of file FlutterTextInputPlugin.mm.

521 {
522 if (_activeModel == nullptr) {
523 return nil;
524 }
525
526 NSString* const textAffinity = [self textAffinityString];
527
528 int composingBase = _activeModel->composing() ? _activeModel->composing_range().base() : -1;
529 int composingExtent = _activeModel->composing() ? _activeModel->composing_range().extent() : -1;
530
531 return @{
532 kSelectionBaseKey : @(_activeModel->selection().base()),
533 kSelectionExtentKey : @(_activeModel->selection().extent()),
534 kSelectionAffinityKey : textAffinity,
536 kComposingBaseKey : @(composingBase),
537 kComposingExtentKey : @(composingExtent),
538 kTextKey : [NSString stringWithUTF8String:_activeModel->GetText().c_str()] ?: [NSNull null],
539 };
540}
static NSString *const kTextKey
static NSString *const kSelectionBaseKey
static NSString *const kSelectionAffinityKey
static NSString *const kComposingExtentKey
static NSString *const kSelectionExtentKey
static NSString *const kComposingBaseKey
static NSString *const kSelectionIsDirectionalKey

◆ enableActiveViewAccessibility

- (void) enableActiveViewAccessibility
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2661 {
2662 if (_activeView.isFirstResponder) {
2663 _activeView.accessibilityEnabled = YES;
2664 }
2665 [self removeEnableFlutterTextInputViewAccessibilityTimer];
2666}

◆ firstRectForCharacterRange:actualRange:

- (NSRect) firstRectForCharacterRange: (NSRange)  range
actualRange: (NSRangePointer)  actualRange 
implementation

Provided by category FlutterTextInputPlugin(TestMethods).

Definition at line 339 of file FlutterTextInputPlugin.mm.

960 :(NSRange)range actualRange:(NSRangePointer)actualRange {
961 // This only determines position of caret instead of any arbitrary range, but it's enough
962 // to properly position accent selection popup
963 return !self.flutterViewController.viewLoaded || CGRectEqualToRect(_caretRect, CGRectNull)
964 ? CGRectZero
965 : [self screenRectFromFrameworkTransform:_caretRect];
966}
FlutterViewController * flutterViewController
CGRect _caretRect

◆ flagsChanged:

- (void) flagsChanged: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

665 :(NSEvent*)event {
666 [self.flutterViewController flagsChanged:event];
667}
FlKeyEvent * event

◆ getOrCreateAutofillableView:isPasswordAutofill:

- (FlutterTextInputView *) getOrCreateAutofillableView: (NSDictionary*)  field
isPasswordAutofill: (BOOL needsPasswordAutofill 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2811 :(NSDictionary*)field
2812 isPasswordAutofill:(BOOL)needsPasswordAutofill {
2813 NSString* autofillId = AutofillIdFromDictionary(field);
2814 FlutterTextInputView* inputView = _autofillContext[autofillId];
2815 if (!inputView) {
2816 inputView =
2817 needsPasswordAutofill ? [FlutterSecureTextInputView alloc] : [FlutterTextInputView alloc];
2818 inputView = [inputView initWithOwner:self];
2819 [self addToInputParentViewIfNeeded:inputView];
2820 }
2821
2822 [inputView configureWithDictionary:field];
2823 return inputView;
2824}
instancetype initWithOwner:(FlutterTextInputPlugin *textInputPlugin)

◆ handleKeyboardWillShow:

- (void) handleKeyboardWillShow: (NSNotification*)  notification
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2368 :(NSNotification*)notification {
2369 NSDictionary* keyboardInfo = [notification userInfo];
2370 NSValue* keyboardFrameEnd = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
2371 _keyboardRect = [keyboardFrameEnd CGRectValue];
2372}

◆ handleKeyEvent:

- (BOOL) handleKeyEvent: (NSEvent*)  event

Handles key down events received from the view controller, responding YES if the event was handled.

Note, the Apple docs suggest that clients should override essentially all the mouse and keyboard event-handling methods of NSResponder. However, experimentation indicates that only key events are processed by the native layer; Flutter processes mouse events. Additionally, processing both keyUp and keyDown results in duplicate processing of the same keys.

Definition at line 339 of file FlutterTextInputPlugin.mm.

605 :(NSEvent*)event {
606 if (event.type == NSEventTypeKeyUp ||
607 (event.type == NSEventTypeFlagsChanged && event.modifierFlags < _previouslyPressedFlags)) {
608 return NO;
609 }
610 _previouslyPressedFlags = event.modifierFlags;
611 if (!_shown) {
612 return NO;
613 }
614
615 _eventProducedOutput = NO;
616 BOOL res = [_textInputContext handleEvent:event];
617 // NSTextInputContext#handleEvent returns YES if the context handles the event. One of the reasons
618 // the event is handled is because it's a key equivalent. But a key equivalent might produce a
619 // text command (indicated by calling doCommandBySelector) or might not (for example, Cmd+Q). In
620 // the latter case, this command somehow has not been executed yet and Flutter must dispatch it to
621 // the next responder. See https://github.com/flutter/flutter/issues/106354 .
622 // The event is also not redispatched if there is IME composition active, because it might be
623 // handled by the IME. See https://github.com/flutter/flutter/issues/134699
624
625 // both NSEventModifierFlagNumericPad and NSEventModifierFlagFunction are set for arrow keys.
626 bool is_navigation = event.modifierFlags & NSEventModifierFlagFunction &&
627 event.modifierFlags & NSEventModifierFlagNumericPad;
628 bool is_navigation_in_ime = is_navigation && self.hasMarkedText;
629
630 if (event.isKeyEquivalent && !is_navigation_in_ime && !_eventProducedOutput) {
631 return NO;
632 }
633 return res;
634}

◆ handleMethodCall:result:

- (void) handleMethodCall: (FlutterMethodCall *)  call
result: (FlutterResult result 

Handles a Flutter system message on the text input channel.

Provided by category FlutterTextInputPlugin(TestMethods).

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2390 NSString* method = call.method;
2391 id args = call.arguments;
2392 if ([method isEqualToString:kShowMethod]) {
2393 [self showTextInput];
2394 result(nil);
2395 } else if ([method isEqualToString:kHideMethod]) {
2396 [self hideTextInput];
2397 result(nil);
2398 } else if ([method isEqualToString:kSetClientMethod]) {
2399 [self setTextInputClient:[args[0] intValue] withConfiguration:args[1]];
2400 result(nil);
2401 } else if ([method isEqualToString:kSetPlatformViewClientMethod]) {
2402 // This method call has a `platformViewId` argument, but we do not need it for iOS for now.
2403 [self setPlatformViewTextInputClient];
2404 result(nil);
2405 } else if ([method isEqualToString:kSetEditingStateMethod]) {
2406 [self setTextInputEditingState:args];
2407 result(nil);
2408 } else if ([method isEqualToString:kClearClientMethod]) {
2409 [self clearTextInputClient];
2410 result(nil);
2411 } else if ([method isEqualToString:kSetEditableSizeAndTransformMethod]) {
2412 [self setEditableSizeAndTransform:args];
2413 result(nil);
2414 } else if ([method isEqualToString:kSetMarkedTextRectMethod]) {
2415 [self updateMarkedRect:args];
2416 result(nil);
2417 } else if ([method isEqualToString:kFinishAutofillContextMethod]) {
2418 [self triggerAutofillSave:[args boolValue]];
2419 result(nil);
2420 // TODO(justinmc): Remove the TextInput method constant when the framework has
2421 // finished transitioning to using the Scribble channel.
2422 // https://github.com/flutter/flutter/pull/104128
2423 } else if ([method isEqualToString:kDeprecatedSetSelectionRectsMethod]) {
2424 [self setSelectionRects:args];
2425 result(nil);
2426 } else if ([method isEqualToString:kSetSelectionRectsMethod]) {
2427 [self setSelectionRects:args];
2428 result(nil);
2429 } else if ([method isEqualToString:kStartLiveTextInputMethod]) {
2430 [self startLiveTextInput];
2431 result(nil);
2432 } else if ([method isEqualToString:kUpdateConfigMethod]) {
2433 [self updateConfig:args];
2434 result(nil);
2435 } else if ([method isEqualToString:kOnInteractiveKeyboardPointerMoveMethod]) {
2436 CGFloat pointerY = (CGFloat)[args[@"pointerY"] doubleValue];
2437 [self handlePointerMove:pointerY];
2438 result(nil);
2439 } else if ([method isEqualToString:kOnInteractiveKeyboardPointerUpMethod]) {
2440 CGFloat pointerY = (CGFloat)[args[@"pointerY"] doubleValue];
2441 [self handlePointerUp:pointerY];
2442 result(nil);
2443 } else {
2445 }
2446}
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
static NSString *const kSetMarkedTextRectMethod
static NSString *const kFinishAutofillContextMethod
static NSString *const kShowMethod
static NSString *const kUpdateConfigMethod
static NSString *const kSetSelectionRectsMethod
static NSString *const kSetPlatformViewClientMethod
static NSString *const kSetEditingStateMethod
static NSString *const kOnInteractiveKeyboardPointerUpMethod
static NSString *const kClearClientMethod
static NSString *const kSetClientMethod
static NSString *const kStartLiveTextInputMethod
static NSString *const kDeprecatedSetSelectionRectsMethod
static NSString *const kHideMethod
static NSString *const kSetEditableSizeAndTransformMethod
static NSString *const kOnInteractiveKeyboardPointerMoveMethod
call(args)
Definition dom.py:159

◆ handlePointerMove:

- (void) handlePointerMove: (CGFloat)  pointerY
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2495 :(CGFloat)pointerY {
2496 // View must be loaded at this point.
2497 UIScreen* screen = _viewController.flutterScreenIfViewLoaded;
2498 CGFloat screenHeight = screen.bounds.size.height;
2499 CGFloat keyboardHeight = _keyboardRect.size.height;
2500 if (screenHeight - keyboardHeight <= pointerY) {
2501 // If the pointer is within the bounds of the keyboard.
2502 if (_keyboardView.superview == nil) {
2503 // If no screenshot has been taken.
2504 [self takeKeyboardScreenshotAndDisplay];
2505 [self hideKeyboardWithoutAnimationAndAvoidCursorDismissUpdate];
2506 } else {
2507 [self setKeyboardContainerHeight:pointerY];
2508 _pointerYVelocity = _previousPointerYPosition - pointerY;
2509 }
2510 } else {
2511 if (_keyboardView.superview != nil) {
2512 // Keeps keyboard at proper height.
2513 _keyboardViewContainer.frame = _keyboardRect;
2514 _pointerYVelocity = _previousPointerYPosition - pointerY;
2515 }
2516 }
2517 _previousPointerYPosition = pointerY;
2518}

◆ handlePointerUp:

- (void) handlePointerUp: (CGFloat)  pointerY
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2448 :(CGFloat)pointerY {
2449 if (_keyboardView.superview != nil) {
2450 // Done to avoid the issue of a pointer up done without a screenshot
2451 // View must be loaded at this point.
2452 UIScreen* screen = _viewController.flutterScreenIfViewLoaded;
2453 CGFloat screenHeight = screen.bounds.size.height;
2454 CGFloat keyboardHeight = _keyboardRect.size.height;
2455 // Negative velocity indicates a downward movement
2456 BOOL shouldDismissKeyboardBasedOnVelocity = _pointerYVelocity < 0;
2457 [UIView animateWithDuration:kKeyboardAnimationTimeToCompleteion
2458 animations:^{
2459 double keyboardDestination =
2460 shouldDismissKeyboardBasedOnVelocity ? screenHeight : screenHeight - keyboardHeight;
2461 _keyboardViewContainer.frame = CGRectMake(
2462 0, keyboardDestination, _viewController.flutterScreenIfViewLoaded.bounds.size.width,
2463 _keyboardViewContainer.frame.size.height);
2464 }
2465 completion:^(BOOL finished) {
2466 if (shouldDismissKeyboardBasedOnVelocity) {
2467 [self.textInputDelegate flutterTextInputView:self.activeView
2468 didResignFirstResponderWithTextInputClient:self.activeView.textInputClient];
2469 [self dismissKeyboardScreenshot];
2470 } else {
2471 [self showKeyboardAndRemoveScreenshot];
2472 }
2473 }];
2474 }
2475}

◆ handlePress:

- (BOOL) handlePress: (ios(13.4))  API_AVAILABLE
implementation

Handles key down events received from the view controller, responding YES if the event was handled.

Definition at line 2342 of file FlutterTextInputPlugin.mm.

3047 :(nonnull FlutterUIPressProxy*)press API_AVAILABLE(ios(13.4)) {
3048 return NO;
3049}
SK_API sk_sp< SkSurface > ios(9.0)

◆ hasMarkedText

- (BOOL) hasMarkedText
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

894 {
895 return _activeModel != nullptr && _activeModel->composing_range().length() > 0;
896}

◆ hideEditMenu

- (void) hideEditMenu
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2565 {
2566 [self.activeView hideEditMenu];
2567}

◆ hideKeyboardWithoutAnimationAndAvoidCursorDismissUpdate

- (void) hideKeyboardWithoutAnimationAndAvoidCursorDismissUpdate
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2526 {
2527 [UIView setAnimationsEnabled:NO];
2528 _cachedFirstResponder = UIApplication.sharedApplication.keyWindow.flutterFirstResponder;
2529 _activeView.preventCursorDismissWhenResignFirstResponder = YES;
2530 [_cachedFirstResponder resignFirstResponder];
2531 _activeView.preventCursorDismissWhenResignFirstResponder = NO;
2532 [UIView setAnimationsEnabled:YES];
2533}

◆ hideTextInput

- (void) hideTextInput
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2668 {
2669 [self removeEnableFlutterTextInputViewAccessibilityTimer];
2670 _activeView.accessibilityEnabled = NO;
2671 [_activeView resignFirstResponder];
2672 [_activeView removeFromSuperview];
2673 [_inputHider removeFromSuperview];
2674}

◆ hostView

- (UIView *) hostView
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2827 {
2828 UIView* host = _viewController.view;
2829 NSAssert(host != nullptr,
2830 @"The application must have a host view since the keyboard client "
2831 @"must be part of the responder chain to function. The host view controller is %@",
2833 return host;
2834}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service host
Definition switches.h:74

◆ indirectScribbleInteraction:didFinishWritingInElement:

- (void) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
didFinishWritingInElement: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2977 :(UIIndirectScribbleInteraction*)interaction
2978 didFinishWritingInElement:(UIScribbleElementIdentifier)elementIdentifier
2979 API_AVAILABLE(ios(14.0)) {
2980}

◆ indirectScribbleInteraction:focusElementIfNeeded:referencePoint:completion:

- (void) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
focusElementIfNeeded: (UIScribbleElementIdentifier)  elementIdentifier
referencePoint: (CGPoint)  focusReferencePoint
completion: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2950 :(UIIndirectScribbleInteraction*)interaction
2951 focusElementIfNeeded:(UIScribbleElementIdentifier)elementIdentifier
2952 referencePoint:(CGPoint)focusReferencePoint
2953 completion:(void (^)(UIResponder<UITextInput>* focusedInput))completion
2954 API_AVAILABLE(ios(14.0)) {
2955 _activeView.scribbleFocusStatus = FlutterScribbleFocusStatusFocusing;
2956 [_indirectScribbleDelegate flutterTextInputPlugin:self
2957 focusElement:elementIdentifier
2958 atPoint:focusReferencePoint
2959 result:^(id _Nullable result) {
2960 _activeView.scribbleFocusStatus =
2961 FlutterScribbleFocusStatusFocused;
2962 completion(_activeView);
2963 }];
2964}

◆ indirectScribbleInteraction:frameForElement:

- (CGRect) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
frameForElement: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2982 :(UIIndirectScribbleInteraction*)interaction
2983 frameForElement:(UIScribbleElementIdentifier)elementIdentifier
2984 API_AVAILABLE(ios(14.0)) {
2985 NSValue* elementValue = [_scribbleElements objectForKey:elementIdentifier];
2986 if (elementValue == nil) {
2987 return CGRectZero;
2988 }
2989 return [elementValue CGRectValue];
2990}

◆ indirectScribbleInteraction:isElementFocused:

- (BOOL) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
isElementFocused: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2944 :(UIIndirectScribbleInteraction*)interaction
2945 isElementFocused:(UIScribbleElementIdentifier)elementIdentifier
2946 API_AVAILABLE(ios(14.0)) {
2947 return _activeView.scribbleFocusStatus == FlutterScribbleFocusStatusFocused;
2948}

◆ indirectScribbleInteraction:requestElementsInRect:completion:

- (void) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
requestElementsInRect: (CGRect)  rect
completion: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2992 :(UIIndirectScribbleInteraction*)interaction
2993 requestElementsInRect:(CGRect)rect
2994 completion:
2995 (void (^)(NSArray<UIScribbleElementIdentifier>* elements))completion
2996 API_AVAILABLE(ios(14.0)) {
2997 [_indirectScribbleDelegate
2998 flutterTextInputPlugin:self
2999 requestElementsInRect:rect
3000 result:^(id _Nullable result) {
3001 NSMutableArray<UIScribbleElementIdentifier>* elements =
3002 [[NSMutableArray alloc] init];
3003 if ([result isKindOfClass:[NSArray class]]) {
3004 for (NSArray* elementArray in result) {
3005 [elements addObject:elementArray[0]];
3006 [_scribbleElements
3007 setObject:[NSValue
3008 valueWithCGRect:CGRectMake(
3009 [elementArray[1] floatValue],
3010 [elementArray[2] floatValue],
3011 [elementArray[3] floatValue],
3012 [elementArray[4] floatValue])]
3013 forKey:elementArray[0]];
3014 }
3015 }
3016 completion(elements);
3017 }];
3018}
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ indirectScribbleInteraction:shouldDelayFocusForElement:

- (BOOL) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
shouldDelayFocusForElement: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2966 :(UIIndirectScribbleInteraction*)interaction
2967 shouldDelayFocusForElement:(UIScribbleElementIdentifier)elementIdentifier
2968 API_AVAILABLE(ios(14.0)) {
2969 return NO;
2970}

◆ indirectScribbleInteraction:willBeginWritingInElement:

- (void) indirectScribbleInteraction: (UIIndirectScribbleInteraction*)  interaction
willBeginWritingInElement: (ios(14.0))  API_AVAILABLE 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2972 :(UIIndirectScribbleInteraction*)interaction
2973 willBeginWritingInElement:(UIScribbleElementIdentifier)elementIdentifier
2974 API_AVAILABLE(ios(14.0)) {
2975}

◆ initWithDelegate:

- (instancetype) initWithDelegate: (id<FlutterTextInputDelegate>)  NS_DESIGNATED_INITIALIZER
Initial value:
{
NSTimer* _enableFlutterTextInputViewAccessibilityTimer

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2349 :(id<FlutterTextInputDelegate>)textInputDelegate {
2350 self = [super init];
2351 if (self) {
2352 // `_textInputDelegate` is a weak reference because it should retain FlutterTextInputPlugin.
2353 _textInputDelegate = textInputDelegate;
2354 _autofillContext = [[NSMutableDictionary alloc] init];
2355 _inputHider = [[FlutterTextInputViewAccessibilityHider alloc] init];
2356 _scribbleElements = [[NSMutableDictionary alloc] init];
2357 _keyboardViewContainer = [[UIView alloc] init];
2358
2359 [[NSNotificationCenter defaultCenter] addObserver:self
2360 selector:@selector(handleKeyboardWillShow:)
2361 name:UIKeyboardWillShowNotification
2362 object:nil];
2363 }
2364
2365 return self;
2366}
id< FlutterTextInputDelegate > textInputDelegate

◆ initWithViewController:

- (instancetype) initWithViewController: (FlutterViewController*)  viewController

Initializes a text input plugin that coordinates key event handling with |viewController|.

Definition at line 339 of file FlutterTextInputPlugin.mm.

343 // The view needs an empty frame otherwise it is visible on dark background.
344 // https://github.com/flutter/flutter/issues/118504
345 self = [super initWithFrame:NSZeroRect];
346 self.clipsToBounds = YES;
347 if (self != nil) {
350 binaryMessenger:viewController.engine.binaryMessenger
352 _shown = FALSE;
353 // NSTextView does not support _weak reference, so this class has to
354 // use __unsafe_unretained and manage the reference by itself.
355 //
356 // Since the dealloc removes the handler, the pointer should
357 // be valid if the handler is ever called.
358 __unsafe_unretained FlutterTextInputPlugin* unsafeSelf = self;
359 [_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
360 [unsafeSelf handleMethodCall:call result:result];
361 }];
362 _textInputContext = [[NSTextInputContext alloc] initWithClient:unsafeSelf];
363 _previouslyPressedFlags = 0;
364
365 // Initialize with the zero matrix which is not
366 // an affine transform.
367 _editableTransform = CATransform3D();
368 _caretRect = CGRectNull;
369 }
370 return self;
371}
fml::scoped_nsobject< UIViewController< FlutterViewResponder > > _flutterViewController
instancetype sharedInstance()
instancetype methodChannelWithName:binaryMessenger:codec:(NSString *name,[binaryMessenger] NSObject< FlutterBinaryMessenger > *messenger,[codec] NSObject< FlutterMethodCodec > *codec)
UIIndirectScribbleInteractionDelegate UIViewController * viewController
CATransform3D _editableTransform
return FALSE

◆ inputContext

- (NSTextInputContext *) inputContext
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

713 {
714 return _textInputContext;
715}

◆ insertNewline:

- (void) insertNewline: (id sender
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

812 :(id)sender {
813 if (_activeModel == nullptr) {
814 return;
815 }
816 if (_activeModel->composing()) {
817 _activeModel->CommitComposing();
818 _activeModel->EndComposing();
819 }
820 if ([self.inputType isEqualToString:kMultilineInputType] &&
821 [self.inputAction isEqualToString:kInputActionNewline]) {
822 [self insertText:@"\n" replacementRange:self.selectedRange];
823 }
824 [_channel invokeMethod:kPerformAction arguments:@[ self.clientID, self.inputAction ]];
825}
static NSString *const kMultilineInputType
static NSString *const kInputActionNewline

◆ insertTab:

- (void) insertTab: (id sender
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

720 :(id)sender {
721 // Implementing insertTab: makes AppKit send tab as command, instead of
722 // insertText with '\t'.
723}

◆ insertText:replacementRange:

- (void) insertText: (id string
replacementRange: (NSRange)  range 
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

725 :(id)string replacementRange:(NSRange)range {
726 if (_activeModel == nullptr) {
727 return;
728 }
729
730 _eventProducedOutput |= true;
731
732 if (range.location != NSNotFound) {
733 // The selected range can actually have negative numbers, since it can start
734 // at the end of the range if the user selected the text going backwards.
735 // Cast to a signed type to determine whether or not the selection is reversed.
736 long signedLength = static_cast<long>(range.length);
737 long location = range.location;
738 long textLength = _activeModel->text_range().end();
739
740 size_t base = std::clamp(location, 0L, textLength);
741 size_t extent = std::clamp(location + signedLength, 0L, textLength);
742
743 _activeModel->SetSelection(flutter::TextRange(base, extent));
744 }
745
746 flutter::TextRange oldSelection = _activeModel->selection();
747 flutter::TextRange composingBeforeChange = _activeModel->composing_range();
748 flutter::TextRange replacedRange(-1, -1);
749
750 std::string textBeforeChange = _activeModel->GetText().c_str();
751 std::string utf8String = [string UTF8String];
752 _activeModel->AddText(utf8String);
753 if (_activeModel->composing()) {
754 replacedRange = composingBeforeChange;
755 _activeModel->CommitComposing();
756 _activeModel->EndComposing();
757 } else {
758 replacedRange = range.location == NSNotFound
759 ? flutter::TextRange(oldSelection.base(), oldSelection.extent())
760 : flutter::TextRange(range.location, range.location + range.length);
761 }
762 if (_enableDeltaModel) {
763 [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange, replacedRange,
764 utf8String)];
765 } else {
766 [self updateEditState];
767 }
768}
size_t base() const
Definition text_range.h:30
size_t extent() const
Definition text_range.h:36
size_t length
SkRange< size_t > TextRange
Definition TextStyle.h:337

◆ isFirstResponder

- (BOOL) isFirstResponder

Whether this plugin is the first responder of this NSWindow.

When accessibility is on, this plugin is set as the first responder to act as the field editor for FlutterTextFields.

Returns false if accessibility is off.

Definition at line 339 of file FlutterTextInputPlugin.mm.

373 {
374 if (!self.flutterViewController.viewLoaded) {
375 return false;
376 }
377 return [self.flutterViewController.view.window firstResponder] == self;
378}

◆ keyDown:

- (void) keyDown: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

639 :(NSEvent*)event {
640 [self.flutterViewController keyDown:event];
641}

◆ keyUp:

- (void) keyUp: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

643 :(NSEvent*)event {
644 [self.flutterViewController keyUp:event];
645}

◆ markedRange

- (NSRange) markedRange
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

885 {
886 if (_activeModel == nullptr) {
887 return NSMakeRange(NSNotFound, 0);
888 }
889 return NSMakeRange(
890 _activeModel->composing_range().base(),
891 _activeModel->composing_range().extent() - _activeModel->composing_range().base());
892}

◆ mouseDown:

- (void) mouseDown: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

669 :(NSEvent*)event {
670 [self.flutterViewController mouseDown:event];
671}

◆ mouseDragged:

- (void) mouseDragged: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

677 :(NSEvent*)event {
678 [self.flutterViewController mouseDragged:event];
679}

◆ mouseMoved:

- (void) mouseMoved: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

705 :(NSEvent*)event {
706 [self.flutterViewController mouseMoved:event];
707}

◆ mouseUp:

- (void) mouseUp: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

673 :(NSEvent*)event {
674 [self.flutterViewController mouseUp:event];
675}

◆ NS_UNAVAILABLE [1/2]

- (instancetype) NS_UNAVAILABLE

◆ NS_UNAVAILABLE [2/2]

+ (instancetype) NS_UNAVAILABLE

◆ otherMouseDown:

- (void) otherMouseDown: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

693 :(NSEvent*)event {
694 [self.flutterViewController otherMouseDown:event];
695}

◆ otherMouseDragged:

- (void) otherMouseDragged: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

701 :(NSEvent*)event {
702 [self.flutterViewController otherMouseDragged:event];
703}

◆ otherMouseUp:

- (void) otherMouseUp: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

697 :(NSEvent*)event {
698 [self.flutterViewController otherMouseUp:event];
699}

◆ performKeyEquivalent:

- (BOOL) performKeyEquivalent: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

647 :(NSEvent*)event {
648 if ([_flutterViewController isDispatchingKeyEvent:event]) {
649 // When NSWindow is nextResponder, keyboard manager will send to it
650 // unhandled events (through [NSWindow keyDown:]). If event has both
651 // control and cmd modifiers set (i.e. cmd+control+space - emoji picker)
652 // NSWindow will then send this event as performKeyEquivalent: to first
653 // responder, which is FlutterTextInputPlugin. If that's the case, the
654 // plugin must not handle the event, otherwise the emoji picker would not
655 // work (due to first responder returning YES from performKeyEquivalent:)
656 // and there would be endless loop, because FlutterViewController will
657 // send the event back to [keyboardManager handleEvent:].
658 return NO;
659 }
660 [event markAsKeyEquivalent];
661 [self.flutterViewController keyDown:event];
662 return YES;
663}

◆ removeEnableFlutterTextInputViewAccessibilityTimer

- (void) removeEnableFlutterTextInputViewAccessibilityTimer
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2378 {
2379 if (_enableFlutterTextInputViewAccessibilityTimer) {
2380 [_enableFlutterTextInputViewAccessibilityTimer invalidate];
2381 _enableFlutterTextInputViewAccessibilityTimer = nil;
2382 }
2383}

◆ resetAllClientIds

- (void) resetAllClientIds
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2890 {
2891 for (UIView* view in self.textInputViews) {
2892 if ([view isKindOfClass:[FlutterTextInputView class]]) {
2893 FlutterTextInputView* inputView = (FlutterTextInputView*)view;
2894 [inputView setTextInputClient:0];
2895 }
2896 }
2897}

◆ resetViewResponder

- (void) resetViewResponder

Definition at line 2342 of file FlutterTextInputPlugin.mm.

3036 {
3037 _viewResponder = nil;
3038}

◆ resignAndRemoveFromSuperview

- (void) resignAndRemoveFromSuperview
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

386 {
387 if (self.superview != nil) {
388 [self.window makeFirstResponder:_flutterViewController.flutterView];
389 [self removeFromSuperview];
390 }
391}

◆ rightMouseDown:

- (void) rightMouseDown: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

681 :(NSEvent*)event {
682 [self.flutterViewController rightMouseDown:event];
683}

◆ rightMouseDragged:

- (void) rightMouseDragged: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

689 :(NSEvent*)event {
690 [self.flutterViewController rightMouseDragged:event];
691}

◆ rightMouseUp:

- (void) rightMouseUp: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

685 :(NSEvent*)event {
686 [self.flutterViewController rightMouseUp:event];
687}

◆ screenRectFromFrameworkTransform:

- (CGRect) screenRectFromFrameworkTransform: (CGRect)  incomingRect
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

917 :(CGRect)incomingRect {
918 CGPoint points[] = {
919 incomingRect.origin,
920 CGPointMake(incomingRect.origin.x, incomingRect.origin.y + incomingRect.size.height),
921 CGPointMake(incomingRect.origin.x + incomingRect.size.width, incomingRect.origin.y),
922 CGPointMake(incomingRect.origin.x + incomingRect.size.width,
923 incomingRect.origin.y + incomingRect.size.height)};
924
925 CGPoint origin = CGPointMake(CGFLOAT_MAX, CGFLOAT_MAX);
926 CGPoint farthest = CGPointMake(-CGFLOAT_MAX, -CGFLOAT_MAX);
927
928 for (int i = 0; i < 4; i++) {
929 const CGPoint point = points[i];
930
931 CGFloat x = _editableTransform.m11 * point.x + _editableTransform.m21 * point.y +
933 CGFloat y = _editableTransform.m12 * point.x + _editableTransform.m22 * point.y +
935
936 const CGFloat w = _editableTransform.m14 * point.x + _editableTransform.m24 * point.y +
938
939 if (w == 0.0) {
940 return CGRectZero;
941 } else if (w != 1.0) {
942 x /= w;
943 y /= w;
944 }
945
946 origin.x = MIN(origin.x, x);
947 origin.y = MIN(origin.y, y);
948 farthest.x = MAX(farthest.x, x);
949 farthest.y = MAX(farthest.y, y);
950 }
951
952 const NSView* fromView = self.flutterViewController.flutterView;
953 const CGRect rectInWindow = [fromView
954 convertRect:CGRectMake(origin.x, origin.y, farthest.x - origin.x, farthest.y - origin.y)
955 toView:nil];
956 NSWindow* window = fromView.window;
957 return window ? [window convertRectToScreen:rectInWindow] : rectInWindow;
958}
static const int points[]
GLFWwindow * window
Definition main.cc:45
double y
double x
SkScalar w

◆ scrollWheel:

- (void) scrollWheel: (NSEvent*)  event
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

709 :(NSEvent*)event {
710 [self.flutterViewController scrollWheel:event];
711}

◆ setEditableSizeAndTransform:

- (void) setEditableSizeAndTransform: (NSDictionary*)  dictionary
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2569 :(NSDictionary*)dictionary {
2570 NSArray* transform = dictionary[@"transform"];
2571 [_activeView setEditableTransform:transform];
2572 const int leftIndex = 12;
2573 const int topIndex = 13;
2574 if ([_activeView isScribbleAvailable]) {
2575 // This is necessary to set up where the scribble interactable element will be.
2576 _inputHider.frame =
2577 CGRectMake([transform[leftIndex] intValue], [transform[topIndex] intValue],
2578 [dictionary[@"width"] intValue], [dictionary[@"height"] intValue]);
2579 _activeView.frame =
2580 CGRectMake(0, 0, [dictionary[@"width"] intValue], [dictionary[@"height"] intValue]);
2581 _activeView.tintColor = [UIColor clearColor];
2582 } else {
2583 // TODO(hellohuanlin): Also need to handle iOS 16 case, where the auto-correction highlight does
2584 // not match the size of text.
2585 // See https://github.com/flutter/flutter/issues/131695
2586 if (@available(iOS 17, *)) {
2587 // Move auto-correction highlight to overlap with the actual text.
2588 // This is to fix an issue where the system auto-correction highlight is displayed at
2589 // the top left corner of the screen on iOS 17+.
2590 // This problem also happens on iOS 16, but the size of highlight does not match the text.
2591 // See https://github.com/flutter/flutter/issues/131695
2592 // TODO(hellohuanlin): Investigate if we can use non-zero size.
2593 _inputHider.frame =
2594 CGRectMake([transform[leftIndex] intValue], [transform[topIndex] intValue], 0, 0);
2595 }
2596 }
2597}
BOOL isScribbleAvailable
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47

◆ setEditableTransform:

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

Definition at line 339 of file FlutterTextInputPlugin.mm.

462 :(NSArray*)matrix {
463 CATransform3D* transform = &_editableTransform;
464
465 transform->m11 = [matrix[0] doubleValue];
466 transform->m12 = [matrix[1] doubleValue];
467 transform->m13 = [matrix[2] doubleValue];
468 transform->m14 = [matrix[3] doubleValue];
469
470 transform->m21 = [matrix[4] doubleValue];
471 transform->m22 = [matrix[5] doubleValue];
472 transform->m23 = [matrix[6] doubleValue];
473 transform->m24 = [matrix[7] doubleValue];
474
475 transform->m31 = [matrix[8] doubleValue];
476 transform->m32 = [matrix[9] doubleValue];
477 transform->m33 = [matrix[10] doubleValue];
478 transform->m34 = [matrix[11] doubleValue];
479
480 transform->m41 = [matrix[12] doubleValue];
481 transform->m42 = [matrix[13] doubleValue];
482 transform->m43 = [matrix[14] doubleValue];
483 transform->m44 = [matrix[15] doubleValue];
484}

◆ setEditingState:

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

Updates the text input model with state received from the framework via the TextInput.setEditingState message.

Definition at line 339 of file FlutterTextInputPlugin.mm.

494 :(NSDictionary*)state {
495 NSString* selectionAffinity = state[kSelectionAffinityKey];
496 if (selectionAffinity != nil) {
497 _textAffinity = [selectionAffinity isEqualToString:kTextAffinityUpstream]
498 ? kFlutterTextAffinityUpstream
499 : kFlutterTextAffinityDownstream;
500 }
501
502 NSString* text = state[kTextKey];
503
505 state[kSelectionBaseKey], state[kSelectionExtentKey], _activeModel->selection());
506 _activeModel->SetSelection(selected_range);
507
508 flutter::TextRange composing_range = RangeFromBaseExtent(
509 state[kComposingBaseKey], state[kComposingExtentKey], _activeModel->composing_range());
510
511 const bool wasComposing = _activeModel->composing();
512 _activeModel->SetText([text UTF8String], selected_range, composing_range);
513 if (composing_range.collapsed() && wasComposing) {
514 [_textInputContext discardMarkedText];
515 }
516 [_client startEditing];
517
518 [self updateTextAndSelection];
519}
bool collapsed() const
Definition text_range.h:77
AtkStateType state
static flutter::TextRange RangeFromBaseExtent(NSNumber *base, NSNumber *extent, const flutter::TextRange &range)

◆ setKeyboardContainerHeight:

- (void) setKeyboardContainerHeight: (CGFloat)  pointerY
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2520 :(CGFloat)pointerY {
2521 CGRect frameRect = _keyboardRect;
2522 frameRect.origin.y = pointerY;
2523 _keyboardViewContainer.frame = frameRect;
2524}

◆ setMarkedText:selectedRange:replacementRange:

- (void) setMarkedText: (id string
selectedRange: (NSRange)  selectedRange
replacementRange: (NSRange)  replacementRange 
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

827 :(id)string
828 selectedRange:(NSRange)selectedRange
829 replacementRange:(NSRange)replacementRange {
830 if (_activeModel == nullptr) {
831 return;
832 }
833 std::string textBeforeChange = _activeModel->GetText().c_str();
834 if (!_activeModel->composing()) {
835 _activeModel->BeginComposing();
836 }
837
838 if (replacementRange.location != NSNotFound) {
839 // According to the NSTextInputClient documentation replacementRange is
840 // computed from the beginning of the marked text. That doesn't seem to be
841 // the case, because in situations where the replacementRange is actually
842 // specified (i.e. when switching between characters equivalent after long
843 // key press) the replacementRange is provided while there is no composition.
844 _activeModel->SetComposingRange(
845 flutter::TextRange(replacementRange.location,
846 replacementRange.location + replacementRange.length),
847 0);
848 }
849
850 flutter::TextRange composingBeforeChange = _activeModel->composing_range();
851 flutter::TextRange selectionBeforeChange = _activeModel->selection();
852
853 // Input string may be NSString or NSAttributedString.
854 BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]];
855 const NSString* rawString = isAttributedString ? [string string] : string;
856 _activeModel->UpdateComposingText(
857 (const char16_t*)[rawString cStringUsingEncoding:NSUTF16StringEncoding],
858 flutter::TextRange(selectedRange.location, selectedRange.location + selectedRange.length));
859
860 if (_enableDeltaModel) {
861 std::string marked_text = [rawString UTF8String];
862 [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange,
863 selectionBeforeChange.collapsed()
864 ? composingBeforeChange
865 : selectionBeforeChange,
866 marked_text)];
867 } else {
868 [self updateEditState];
869 }
870}

◆ setPlatformViewTextInputClient

- (void) setPlatformViewTextInputClient
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2693 {
2694 // No need to track the platformViewID (unlike in Android). When a platform view
2695 // becomes the first responder, simply hide this dummy text input view (`_activeView`)
2696 // for the previously focused widget.
2697 [self removeEnableFlutterTextInputViewAccessibilityTimer];
2698 _activeView.accessibilityEnabled = NO;
2699 [_activeView removeFromSuperview];
2700 [_inputHider removeFromSuperview];
2701}

◆ setSelectionRects:

- (void) setSelectionRects: (NSArray*)  encodedRects
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2608 :(NSArray*)encodedRects {
2609 NSMutableArray<FlutterTextSelectionRect*>* rectsAsRect =
2610 [[NSMutableArray alloc] initWithCapacity:[encodedRects count]];
2611 for (NSUInteger i = 0; i < [encodedRects count]; i++) {
2612 NSArray<NSNumber*>* encodedRect = encodedRects[i];
2613 [rectsAsRect addObject:[FlutterTextSelectionRect
2614 selectionRectWithRect:CGRectMake([encodedRect[0] floatValue],
2615 [encodedRect[1] floatValue],
2616 [encodedRect[2] floatValue],
2617 [encodedRect[3] floatValue])
2618 position:[encodedRect[4] unsignedIntegerValue]
2619 writingDirection:[encodedRect[5] unsignedIntegerValue] == 1
2620 ? NSWritingDirectionLeftToRight
2621 : NSWritingDirectionRightToLeft]];
2622 }
2623
2624 // TODO(hellohuanlin): Investigate why notifying the text input system about text changes (via
2625 // textWillChange and textDidChange APIs) causes a bug where we cannot enter text with IME
2626 // keyboards. Issue: https://github.com/flutter/flutter/issues/133908
2627 _activeView.selectionRects = rectsAsRect;
2628}

◆ setTextInputClient:withConfiguration:

- (void) setTextInputClient: (int client
withConfiguration: (NSDictionary*)  configuration 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2703 :(int)client withConfiguration:(NSDictionary*)configuration {
2705 // Hide all input views from autofill, only make those in the new configuration visible
2706 // to autofill.
2707 [self changeInputViewsAutofillVisibility:NO];
2708
2709 // Update the current active view.
2710 switch (AutofillTypeOf(configuration)) {
2711 case kFlutterAutofillTypeNone:
2712 self.activeView = [self createInputViewWith:configuration];
2713 break;
2714 case kFlutterAutofillTypeRegular:
2715 // If the group does not involve password autofill, only install the
2716 // input view that's being focused.
2717 self.activeView = [self updateAndShowAutofillViews:nil
2718 focusedField:configuration
2719 isPasswordRelated:NO];
2720 break;
2721 case kFlutterAutofillTypePassword:
2722 self.activeView = [self updateAndShowAutofillViews:configuration[kAssociatedAutofillFields]
2723 focusedField:configuration
2724 isPasswordRelated:YES];
2725 break;
2726 }
2727 [_activeView setTextInputClient:client];
2728 [_activeView reloadInputViews];
2729
2730 // Clean up views that no longer need to be in the view hierarchy, according to
2731 // the current autofill context. The "garbage" input views are already made
2732 // invisible to autofill and they can't `becomeFirstResponder`, we only remove
2733 // them to free up resources and reduce the number of input views in the view
2734 // hierarchy.
2735 //
2736 // The garbage views are decommissioned immediately, but the removeFromSuperview
2737 // call is scheduled on the runloop and delayed by 0.1s so we don't remove the
2738 // text fields immediately (which seems to make the keyboard flicker).
2739 // See: https://github.com/flutter/flutter/issues/64628.
2740 [self cleanUpViewHierarchy:NO clearText:YES delayRemoval:YES];
2741}
Type::kYUV Type::kRGBA() int(0.7 *637)

◆ setTextInputEditingState:

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

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2916 :(NSDictionary*)state {
2917 [_activeView setTextInputState:state];
2918}

◆ setUpIndirectScribbleInteraction:

- (void) setUpIndirectScribbleInteraction: (id<FlutterViewResponder>)  viewResponder

These are used by the UIIndirectScribbleInteractionDelegate methods to handle focusing on the correct element.

Definition at line 2342 of file FlutterTextInputPlugin.mm.

3022 :(id<FlutterViewResponder>)viewResponder {
3023 if (_viewResponder != viewResponder) {
3024 if (@available(iOS 14.0, *)) {
3025 UIView* parentView = viewResponder.view;
3026 if (parentView != nil) {
3027 UIIndirectScribbleInteraction* scribbleInteraction = [[UIIndirectScribbleInteraction alloc]
3028 initWithDelegate:(id<UIIndirectScribbleInteractionDelegate>)self];
3029 [parentView addInteraction:scribbleInteraction];
3030 }
3031 }
3032 }
3033 _viewResponder = viewResponder;
3034}
id< FlutterViewResponder > viewResponder

◆ showEditMenu:

- (BOOL) showEditMenu: (ios(16.0))  API_AVAILABLE

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2552 :(NSDictionary*)args API_AVAILABLE(ios(16.0)) {
2553 if (!self.activeView.isFirstResponder) {
2554 return NO;
2555 }
2556 NSDictionary<NSString*, NSNumber*>* encodedTargetRect = args[@"targetRect"];
2557 CGRect globalTargetRect = CGRectMake(
2558 [encodedTargetRect[@"x"] doubleValue], [encodedTargetRect[@"y"] doubleValue],
2559 [encodedTargetRect[@"width"] doubleValue], [encodedTargetRect[@"height"] doubleValue]);
2560 CGRect localTargetRect = [self.hostView convertRect:globalTargetRect toView:self.activeView];
2561 [self.activeView showEditMenuWithTargetRect:localTargetRect];
2562 return YES;
2563}
FlutterTextInputView * activeView

◆ showKeyboardAndRemoveScreenshot

- (void) showKeyboardAndRemoveScreenshot
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2483 {
2484 [UIView setAnimationsEnabled:NO];
2485 [_cachedFirstResponder becomeFirstResponder];
2486 // UIKit does not immediately access the areAnimationsEnabled Boolean so a delay is needed before
2487 // returned
2488 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kKeyboardAnimationDelaySeconds * NSEC_PER_SEC),
2489 dispatch_get_main_queue(), ^{
2490 [UIView setAnimationsEnabled:YES];
2491 [self dismissKeyboardScreenshot];
2492 });
2493}
static const NSTimeInterval kKeyboardAnimationDelaySeconds
#define NSEC_PER_SEC
Definition timerfd.cc:35

◆ showTextInput

- (void) showTextInput
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2639 {
2640 _activeView.viewResponder = _viewResponder;
2641 [self addToInputParentViewIfNeeded:_activeView];
2642 // Adds a delay to prevent the text view from receiving accessibility
2643 // focus in case it is activated during semantics updates.
2644 //
2645 // One common case is when the app navigates to a page with an auto
2646 // focused text field. The text field will activate the FlutterTextInputView
2647 // with a semantics update sent to the engine. The voiceover will focus
2648 // the newly attached active view while performing accessibility update.
2649 // This results in accessibility focus stuck at the FlutterTextInputView.
2650 if (!_enableFlutterTextInputViewAccessibilityTimer) {
2651 _enableFlutterTextInputViewAccessibilityTimer =
2652 [NSTimer scheduledTimerWithTimeInterval:kUITextInputAccessibilityEnablingDelaySeconds
2654 selector:@selector(enableActiveViewAccessibility)
2655 userInfo:nil
2656 repeats:NO];
2657 }
2658 [_activeView becomeFirstResponder];
2659}
instancetype proxyWithTarget:(FlutterTextInputPlugin *target)

◆ startLiveTextInput

- (void) startLiveTextInput
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2630 {
2631 if (@available(iOS 15.0, *)) {
2632 if (_activeView == nil || !_activeView.isFirstResponder) {
2633 return;
2634 }
2635 [_activeView captureTextFromCamera:nil];
2636 }
2637}

◆ takeKeyboardScreenshotAndDisplay

- (void) takeKeyboardScreenshotAndDisplay
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2535 {
2536 // View must be loaded at this point
2537 UIScreen* screen = _viewController.flutterScreenIfViewLoaded;
2538 UIView* keyboardSnap = [screen snapshotViewAfterScreenUpdates:YES];
2539 keyboardSnap = [keyboardSnap resizableSnapshotViewFromRect:_keyboardRect
2540 afterScreenUpdates:YES
2541 withCapInsets:UIEdgeInsetsZero];
2542 _keyboardView = keyboardSnap;
2543 [_keyboardViewContainer addSubview:_keyboardView];
2544 if (_keyboardViewContainer.superview == nil) {
2545 [UIApplication.sharedApplication.delegate.window.rootViewController.view
2546 addSubview:_keyboardViewContainer];
2547 }
2548 _keyboardViewContainer.layer.zPosition = NSIntegerMax;
2549 _keyboardViewContainer.frame = _keyboardRect;
2550}

◆ textAffinityString

- (NSString *) textAffinityString
implementation

Return the string representation of the current textAffinity as it should be sent over the FlutterMethodChannel.

Definition at line 339 of file FlutterTextInputPlugin.mm.

600 {
601 return (self.textAffinity == kFlutterTextAffinityUpstream) ? kTextAffinityUpstream
603}
static FLUTTER_ASSERT_ARC const char kTextAffinityDownstream[]
static const char kTextAffinityUpstream[]

◆ textInputView

- (UIView< UITextInput > *) textInputView

The UITextInput implementation used to control text entry.

This is used by AccessibilityBridge to forward interactions with iOS' accessibility system.

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2385 {
2386 return _activeView;
2387}

◆ textInputViews

- (NSArray< UIView * > *) textInputViews
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2837 {
2838 return _inputHider.subviews;
2839}

◆ triggerAutofillSave:

- (void) triggerAutofillSave: (BOOL saveEntries
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2676 :(BOOL)saveEntries {
2677 [_activeView resignFirstResponder];
2678
2679 if (saveEntries) {
2680 // Make all the input fields in the autofill context visible,
2681 // then remove them to trigger autofill save.
2682 [self cleanUpViewHierarchy:YES clearText:YES delayRemoval:NO];
2683 [_autofillContext removeAllObjects];
2684 [self changeInputViewsAutofillVisibility:YES];
2685 } else {
2686 [_autofillContext removeAllObjects];
2687 }
2688
2689 [self cleanUpViewHierarchy:YES clearText:!saveEntries delayRemoval:NO];
2690 [self addToInputParentViewIfNeeded:_activeView];
2691}

◆ unmarkText

- (void) unmarkText
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

872 {
873 if (_activeModel == nullptr) {
874 return;
875 }
876 _activeModel->CommitComposing();
877 _activeModel->EndComposing();
878 if (_enableDeltaModel) {
879 [self updateEditStateWithDelta:flutter::TextEditingDelta(_activeModel->GetText().c_str())];
880 } else {
881 [self updateEditState];
882 }
883}

◆ updateAndShowAutofillViews:focusedField:isPasswordRelated:

- (FlutterTextInputView *) updateAndShowAutofillViews: (NSArray*)  fields
focusedField: (NSDictionary*)  focusedField
isPasswordRelated: (BOOL isPassword 
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2766 :(NSArray*)fields
2767 focusedField:(NSDictionary*)focusedField
2768 isPasswordRelated:(BOOL)isPassword {
2769 FlutterTextInputView* focused = nil;
2770 NSString* focusedId = AutofillIdFromDictionary(focusedField);
2771 NSAssert(focusedId, @"autofillId must not be null for the focused field: %@", focusedField);
2772
2773 if (!fields) {
2774 // DO NOT push the current autofillable input fields to the context even
2775 // if it's password-related, because it is not in an autofill group.
2776 focused = [self getOrCreateAutofillableView:focusedField isPasswordAutofill:isPassword];
2777 [_autofillContext removeObjectForKey:focusedId];
2778 }
2779
2780 for (NSDictionary* field in fields) {
2781 NSString* autofillId = AutofillIdFromDictionary(field);
2782 NSAssert(autofillId, @"autofillId must not be null for field: %@", field);
2783
2784 BOOL hasHints = AutofillTypeOf(field) != kFlutterAutofillTypeNone;
2785 BOOL isFocused = [focusedId isEqualToString:autofillId];
2786
2787 if (isFocused) {
2788 focused = [self getOrCreateAutofillableView:field isPasswordAutofill:isPassword];
2789 }
2790
2791 if (hasHints) {
2792 // Push the current input field to the context if it has hints.
2793 _autofillContext[autofillId] = isFocused ? focused
2794 : [self getOrCreateAutofillableView:field
2795 isPasswordAutofill:isPassword];
2796 } else {
2797 // Mark for deletion.
2798 [_autofillContext removeObjectForKey:autofillId];
2799 }
2800 }
2801
2802 NSAssert(focused, @"The current focused input view must not be nil.");
2803 return focused;
2804}

◆ updateCaretRect:

- (void) updateCaretRect: (NSDictionary*)  dictionary
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

486 :(NSDictionary*)dictionary {
487 NSAssert(dictionary[@"x"] != nil && dictionary[@"y"] != nil && dictionary[@"width"] != nil &&
488 dictionary[@"height"] != nil,
489 @"Expected a dictionary representing a CGRect, got %@", dictionary);
490 _caretRect = CGRectMake([dictionary[@"x"] doubleValue], [dictionary[@"y"] doubleValue],
491 [dictionary[@"width"] doubleValue], [dictionary[@"height"] doubleValue]);
492}

◆ updateConfig:

- (void) updateConfig: (NSDictionary*)  dictionary
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2925 :(NSDictionary*)dictionary {
2926 BOOL isSecureTextEntry = [dictionary[kSecureTextEntry] boolValue];
2927 for (UIView* view in self.textInputViews) {
2928 if ([view isKindOfClass:[FlutterTextInputView class]]) {
2929 FlutterTextInputView* inputView = (FlutterTextInputView*)view;
2930 // The feature of holding and draging spacebar to move cursor is affected by
2931 // secureTextEntry, so when obscureText is updated, we need to update secureTextEntry
2932 // and call reloadInputViews.
2933 // https://github.com/flutter/flutter/issues/122139
2934 if (inputView.isSecureTextEntry != isSecureTextEntry) {
2935 inputView.secureTextEntry = isSecureTextEntry;
2936 [inputView reloadInputViews];
2937 }
2938 }
2939 }
2940}

◆ updateEditState

- (void) updateEditState
implementation

Informs the Flutter framework of changes to the text input model's state by sending the entire new state.

Definition at line 339 of file FlutterTextInputPlugin.mm.

542 {
543 if (_activeModel == nullptr) {
544 return;
545 }
546
547 NSDictionary* state = [self editingState];
548 [_channel invokeMethod:kUpdateEditStateResponseMethod arguments:@[ self.clientID, state ]];
549 [self updateTextAndSelection];
550}

◆ updateEditStateWithDelta:

- (void) updateEditStateWithDelta: (const flutter::TextEditingDelta delta
implementation

Informs the Flutter framework of changes to the text input model's state by sending only the difference.

Definition at line 339 of file FlutterTextInputPlugin.mm.

552 :(const flutter::TextEditingDelta)delta {
553 NSUInteger selectionBase = _activeModel->selection().base();
554 NSUInteger selectionExtent = _activeModel->selection().extent();
555 int composingBase = _activeModel->composing() ? _activeModel->composing_range().base() : -1;
556 int composingExtent = _activeModel->composing() ? _activeModel->composing_range().extent() : -1;
557
558 NSString* const textAffinity = [self textAffinityString];
559
560 NSDictionary* deltaToFramework = @{
561 @"oldText" : @(delta.old_text().c_str()),
562 @"deltaText" : @(delta.delta_text().c_str()),
563 @"deltaStart" : @(delta.delta_start()),
564 @"deltaEnd" : @(delta.delta_end()),
565 @"selectionBase" : @(selectionBase),
566 @"selectionExtent" : @(selectionExtent),
567 @"selectionAffinity" : textAffinity,
568 @"selectionIsDirectional" : @(false),
569 @"composingBase" : @(composingBase),
570 @"composingExtent" : @(composingExtent),
571 };
572
573 NSDictionary* deltas = @{
574 @"deltas" : @[ deltaToFramework ],
575 };
576
577 [_channel invokeMethod:kUpdateEditStateWithDeltasResponseMethod
578 arguments:@[ self.clientID, deltas ]];
579 [self updateTextAndSelection];
580}
A change in the state of an input field.

◆ updateMarkedRect:

- (void) updateMarkedRect: (NSDictionary*)  dictionary
implementation

Definition at line 2342 of file FlutterTextInputPlugin.mm.

2599 :(NSDictionary*)dictionary {
2600 NSAssert(dictionary[@"x"] != nil && dictionary[@"y"] != nil && dictionary[@"width"] != nil &&
2601 dictionary[@"height"] != nil,
2602 @"Expected a dictionary representing a CGRect, got %@", dictionary);
2603 CGRect rect = CGRectMake([dictionary[@"x"] doubleValue], [dictionary[@"y"] doubleValue],
2604 [dictionary[@"width"] doubleValue], [dictionary[@"height"] doubleValue]);
2605 _activeView.markedRect = rect.size.width < 0 && rect.size.height < 0 ? kInvalidFirstRect : rect;
2606}
const CGRect kInvalidFirstRect

◆ updateTextAndSelection

- (void) updateTextAndSelection
implementation

Updates the stringValue and selectedRange that stored in the NSTextView interface that this plugin inherits from.

If there is a FlutterTextField uses this plugin as its field editor, this method will update the stringValue and selectedRange through the API of the FlutterTextField.

Definition at line 339 of file FlutterTextInputPlugin.mm.

582 {
583 NSAssert(_activeModel != nullptr, @"Flutter text model must not be null.");
584 NSString* text = @(_activeModel->GetText().data());
585 int start = _activeModel->selection().base();
586 int extend = _activeModel->selection().extent();
587 NSRange selection = NSMakeRange(MIN(start, extend), ABS(start - extend));
588 // There may be a native text field client if VoiceOver is on.
589 // In this case, this plugin has to update text and selection through
590 // the client in order for VoiceOver to announce the text editing
591 // properly.
592 if (_client) {
593 [_client updateString:text withSelection:selection];
594 } else {
595 self.string = text;
596 [self setSelectedRange:selection];
597 }
598}

◆ validAttributesForMarkedText

- (NSArray< NSString * > *) validAttributesForMarkedText
implementation

Definition at line 339 of file FlutterTextInputPlugin.mm.

911 {
912 return @[];
913}

Member Data Documentation

◆ __pad0__

- __pad0__
protected

Definition at line 179 of file FlutterTextInputPlugin.h.

Property Documentation

◆ activeView

- (FlutterTextInputView *) activeView
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2333 of file FlutterTextInputPlugin.mm.

◆ autofillContext

- (NSMutableDictionary< NSString *, FlutterTextInputView * > *) autofillContext
readnonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2332 of file FlutterTextInputPlugin.mm.

◆ cachedFirstResponder

- (UIView *) cachedFirstResponder
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2339 of file FlutterTextInputPlugin.mm.

◆ channel

- (FlutterMethodChannel*) channel
readwritenonatomicassignimplementation

The channel used to communicate with Flutter.

Provided by category FlutterTextInputPlugin().

Definition at line 215 of file FlutterTextInputPlugin.mm.

◆ client

- (FlutterTextField*) client
readwritenonatomicweak

The NSTextField that currently has this plugin as its field editor.

Must be nil if accessibility is off.

Definition at line 34 of file FlutterTextInputPlugin.h.

◆ clientID

- (NSNumber*) clientID
readwritenonatomicassignimplementation

ID of the text input client.

Provided by category FlutterTextInputPlugin().

Definition at line 242 of file FlutterTextInputPlugin.mm.

◆ customRunLoopMode

- (NSString*) customRunLoopMode
readwritenonatomicassignimplementation

Allow overriding run loop mode for test.

Provided by category FlutterTextInputPlugin(TestMethods).

Definition at line 319 of file FlutterTextInputPlugin.mm.

◆ enableDeltaModel

- (BOOL) enableDeltaModel
readwritenonatomicassignimplementation

Whether to enable the sending of text input updates from the engine to the framework as TextEditingDeltas rather than as one TextEditingValue. For more information on the delta model, see: https://master-api.flutter.dev/flutter/services/TextInputConfiguration/enableDeltaModel.html

Provided by category FlutterTextInputPlugin().

Definition at line 269 of file FlutterTextInputPlugin.mm.

◆ eventProducedOutput

- (BOOL) eventProducedOutput
readwritenonatomicassignimplementation

Set to true if the last event fed to the input context produced a text editing command or text output. It is reset to false at the beginning of every key event, and is only used while processing this event.

Provided by category FlutterTextInputPlugin().

Definition at line 261 of file FlutterTextInputPlugin.mm.

◆ flutterViewController

- (FlutterViewController*) flutterViewController
readwritenonatomicweakimplementation

The FlutterViewController to manage input for.

Provided by category FlutterTextInputPlugin().

Definition at line 220 of file FlutterTextInputPlugin.mm.

◆ indirectScribbleDelegate

- (id<FlutterIndirectScribbleDelegate>) indirectScribbleDelegate
readwritenonatomicweak

Definition at line 37 of file FlutterTextInputPlugin.h.

◆ inputAction

- (NSString*) inputAction
readwritenonatomicassignimplementation

An action requested by the user on the input client. See available options: https://api.flutter.dev/flutter/services/TextInputAction-class.html

Provided by category FlutterTextInputPlugin().

Definition at line 254 of file FlutterTextInputPlugin.mm.

◆ inputHider [1/2]

- (FlutterTextInputViewAccessibilityHider*) inputHider
readwritenonatomicretainimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2334 of file FlutterTextInputPlugin.mm.

◆ inputHider [2/2]

- (UIView*) inputHider
readnonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 64 of file FlutterTextInputPluginTest.mm.

◆ inputType

- (NSString*) inputType
readwritenonatomicassignimplementation

Keyboard type of the client. See available options: https://api.flutter.dev/flutter/services/TextInputType-class.html

Provided by category FlutterTextInputPlugin().

Definition at line 248 of file FlutterTextInputPlugin.mm.

◆ keyboardRect

- (CGRect) keyboardRect
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2340 of file FlutterTextInputPlugin.mm.

◆ keyboardView

- (UIView *) keyboardView
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2338 of file FlutterTextInputPlugin.mm.

◆ keyboardViewContainer

- (UIView *) keyboardViewContainer
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2337 of file FlutterTextInputPlugin.mm.

◆ pendingSelectors

- (NSMutableArray*) pendingSelectors
readwritenonatomicassignimplementation

Used to gather multiple selectors performed in one run loop turn. These will be all sent in one platform channel call so that the framework can process them in single microtask.

Provided by category FlutterTextInputPlugin().

Definition at line 276 of file FlutterTextInputPlugin.mm.

◆ pointerYVelocity

- (CGFloat) pointerYVelocity
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2342 of file FlutterTextInputPlugin.mm.

◆ previouslyPressedFlags

- (uint64_t) previouslyPressedFlags
readwritenonatomicassignimplementation

The current state of the keyboard and pressed keys.

Provided by category FlutterTextInputPlugin().

Definition at line 232 of file FlutterTextInputPlugin.mm.

◆ previousPointerYPosition

- (CGFloat) previousPointerYPosition
readwritenonatomicassignimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2341 of file FlutterTextInputPlugin.mm.

◆ scribbleElements

- (NSMutableDictionary<UIScribbleElementIdentifier, NSValue*>*) scribbleElements
readwritenonatomicstrong

Definition at line 39 of file FlutterTextInputPlugin.h.

◆ shown

- (BOOL) shown
readwritenonatomicassignimplementation

Whether the text input is shown in the view.

Defaults to TRUE on startup.

Provided by category FlutterTextInputPlugin().

Definition at line 227 of file FlutterTextInputPlugin.mm.

◆ textAffinity

- (FlutterTextAffinity) textAffinity
readwriteatomicimplementation

The affinity for the current cursor position.

Provided by category FlutterTextInputPlugin().

Definition at line 237 of file FlutterTextInputPlugin.mm.

◆ textInputContext

- (NSTextInputContext*) textInputContext
readwritenonatomicassignimplementation

A text input context, representing a connection to the Cocoa text input system.

Provided by category FlutterTextInputPlugin(TestMethods).

Definition at line 210 of file FlutterTextInputPlugin.mm.

◆ textInputDelegate

- (id<FlutterTextInputDelegate>) textInputDelegate
readnonatomicweakimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 779 of file FlutterTextInputPlugin.mm.

◆ viewController

- (UIIndirectScribbleInteractionDelegate UIViewController*) viewController
readwritenonatomicweak

Definition at line 36 of file FlutterTextInputPlugin.h.

◆ viewResponder

- (id<FlutterViewResponder>) viewResponder
readnonatomicweakimplementation

Provided by category FlutterTextInputPlugin().

Definition at line 2335 of file FlutterTextInputPlugin.mm.


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