11 #include "flutter/third_party/accessibility/ax/ax_action_data.h"
12 #include "flutter/third_party/accessibility/gfx/geometry/rect_conversions.h"
13 #include "flutter/third_party/accessibility/gfx/mac/coordinate_conversion.h"
15 #pragma mark - FlutterTextFieldCell
28 - (instancetype)initWithTextField:(NSTextField*)textField fieldEditor:(NSTextView*)editor;
36 #pragma mark - Private
38 - (instancetype)initWithTextField:(NSTextField*)textField fieldEditor:(NSTextView*)editor {
39 self = [
super initTextCell:textField.stringValue];
42 [
self setControlView:textField];
47 self.selectable = YES;
54 - (NSTextView*)fieldEditorForView:(NSView*)controlView {
60 #pragma mark - FlutterTextField
69 - (instancetype)initWithPlatformNode:(
flutter::FlutterTextPlatformNode*)node
71 self = [
super initWithFrame:NSZeroRect];
80 - (void)updateString:(NSString*)string withSelection:(NSRange)selection {
82 @"Can't update FlutterTextField when it is not the first responder");
83 if (![[
self stringValue] isEqualToString:
string]) {
84 [
self setStringValue:string];
86 if (!NSEqualRanges(
_plugin.selectedRange, selection)) {
87 [_plugin setSelectedRange:selection];
97 return _node->GetFrame();
100 #pragma mark - NSAccessibilityProtocol
102 - (void)setAccessibilityFocused:(BOOL)isFocused {
106 [
super setAccessibilityFocused:isFocused];
107 ui::AXActionData data;
108 data.action = isFocused ? ax::mojom::Action::kFocus : ax::mojom::Action::kBlur;
109 _node->GetDelegate()->AccessibilityPerformAction(data);
112 - (void)startEditing {
116 if (
self.currentEditor ==
_plugin) {
124 [
self selectText:self];
125 NSAssert(
self.currentEditor ==
_plugin,
@"Failed to set current editor");
130 NSString* textValue = @(_node->GetStringAttribute(ax::mojom::StringAttribute::kValue).data());
131 int start = _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart);
132 int end = _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd);
133 NSAssert((start >= 0 && end >= 0) || (start == -1 && end == -1),
@"selection is invalid");
135 if (start >= 0 && end >= 0) {
136 selection = NSMakeRange(MIN(start, end), ABS(end - start));
140 selection = NSMakeRange([
self stringValue].length, 0);
145 - (void)setPlatformNode:(
flutter::FlutterTextPlatformNode*)node {
149 #pragma mark - NSObject
164 view_controller_ = view_controller;
167 fieldEditor:view_controller.textInputPlugin];
168 appkit_text_field_.bezeled = NO;
169 appkit_text_field_.drawsBackground = NO;
170 appkit_text_field_.bordered = NO;
171 appkit_text_field_.focusRingType = NSFocusRingTypeNone;
176 EnsureDetachedFromView();
180 if (EnsureAttachedToView()) {
181 return appkit_text_field_;
187 if (!view_controller_.viewLoaded) {
193 gfx::RectF bounds = bridge_ptr->RelativeToGlobalBounds(delegate->
GetAXNode(), offscreen,
true);
196 NSRect ns_local_bounds = NSMakeRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
201 ns_local_bounds.origin.y = -ns_local_bounds.origin.y - ns_local_bounds.size.height;
202 NSRect ns_view_bounds = [
view_controller_.flutterView convertRectFromBacking:ns_local_bounds];
203 return [
view_controller_.flutterView convertRect:ns_view_bounds toView:nil];
206 bool FlutterTextPlatformNode::EnsureAttachedToView() {
207 if (!view_controller_.viewLoaded) {
210 if ([appkit_text_field_ isDescendantOf:view_controller_.view]) {
213 [view_controller_.view addSubview:appkit_text_field_
214 positioned:NSWindowBelow
215 relativeTo:view_controller_.flutterView];
219 void FlutterTextPlatformNode::EnsureDetachedFromView() {
220 [appkit_text_field_ removeFromSuperview];