Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ @implementation FlutterTextInputPlugin {
* The currently active text input model.
*/
std::unique_ptr<flutter::TextInputModel> _activeModel;

/**
* Transform for current the editable. Used to determine position of accent selection menu.
*/
CATransform3D _editableTransform;

/**
* Current position of caret in local (editable) coordinates.
*/
CGRect _caretRect;
}

- (instancetype)initWithViewController:(FlutterViewController*)viewController {
Expand All @@ -152,6 +162,11 @@ - (instancetype)initWithViewController:(FlutterViewController*)viewController {
}];
_textInputContext = [[NSTextInputContext alloc] initWithClient:self];
_previouslyPressedFlags = 0;

// Initialize with the zero matrix which is not
// an affine transform.
_editableTransform = CATransform3D();
_caretRect = CGRectNull;
}
return self;
}
Expand Down Expand Up @@ -200,12 +215,50 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
// engine since it sent this update, and needs to now be made to match the
// engine's version of the state.
[self updateEditState];
} else if ([method isEqualToString:@"TextInput.setEditableSizeAndTransform"]) {
NSDictionary* state = call.arguments;
[self setEditableTransform:state[@"transform"]];
} else if ([method isEqualToString:@"TextInput.setCaretRect"]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments on flutter/flutter#77608. I'd have thought that TextInput.setMarkedTextRect should be sufficient here -- despite its name, it should emit the current caret rect when the composing range is empty.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted in flutter/flutter#77608, TextInput.setMarkedTextRect only works while compositing. So we need another method for caret position.

NSDictionary* rect = call.arguments;
[self updateCaretRect:rect];
} else {
handled = NO;
}
result(handled ? nil : FlutterMethodNotImplemented);
}

- (void)setEditableTransform:(NSArray*)matrix {
CATransform3D* transform = &_editableTransform;

transform->m11 = [matrix[0] doubleValue];
transform->m12 = [matrix[1] doubleValue];
transform->m13 = [matrix[2] doubleValue];
transform->m14 = [matrix[3] doubleValue];

transform->m21 = [matrix[4] doubleValue];
transform->m22 = [matrix[5] doubleValue];
transform->m23 = [matrix[6] doubleValue];
transform->m24 = [matrix[7] doubleValue];

transform->m31 = [matrix[8] doubleValue];
transform->m32 = [matrix[9] doubleValue];
transform->m33 = [matrix[10] doubleValue];
transform->m34 = [matrix[11] doubleValue];

transform->m41 = [matrix[12] doubleValue];
transform->m42 = [matrix[13] doubleValue];
transform->m43 = [matrix[14] doubleValue];
transform->m44 = [matrix[15] doubleValue];
}

- (void)updateCaretRect:(NSDictionary*)dictionary {
NSAssert(dictionary[@"x"] != nil && dictionary[@"y"] != nil && dictionary[@"width"] != nil &&
dictionary[@"height"] != nil,
@"Expected a dictionary representing a CGRect, got %@", dictionary);
_caretRect = CGRectMake([dictionary[@"x"] doubleValue], [dictionary[@"y"] doubleValue],
[dictionary[@"width"] doubleValue], [dictionary[@"height"] doubleValue]);
}

- (void)setEditingState:(NSDictionary*)state {
NSString* selectionAffinity = state[kSelectionAffinityKey];
if (selectionAffinity != nil) {
Expand Down Expand Up @@ -403,9 +456,19 @@ - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
}

- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
// TODO: Implement.
// Note: This function can't easily be implemented under the system-message architecture.
return CGRectZero;
// This only determines position of caret instead of any arbitrary range, but it's enough
// to properly position accent selection popup
if (CATransform3DIsAffine(_editableTransform) && !CGRectEqualToRect(_caretRect, CGRectNull)) {
CGRect rect =
CGRectApplyAffineTransform(_caretRect, CATransform3DGetAffineTransform(_editableTransform));

// flip and convert to screen coordinates
double viewHeight = self.flutterViewController.view.bounds.size.height;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@knopp knopp Apr 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that :)

Should be fixed in #25524 .

rect.origin.y = viewHeight - rect.origin.y;
return [self.flutterViewController.view.window convertRectToScreen:rect];
} else {
return CGRectZero;
}
}

- (NSUInteger)characterIndexForPoint:(NSPoint)point {
Expand Down