-
Notifications
You must be signed in to change notification settings - Fork 6k
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the Objective-C objects need to be prefixed with some sort of a flutter specific identifier.
@@ -20,7 +20,7 @@ AccessibilityBridge::AccessibilityBridge(app::ApplicationContext* context) | |||
: writer_(context->ConnectToEnvironmentService<maxwell::ContextWriter>()) {} | |||
|
|||
void AccessibilityBridge::UpdateSemantics( | |||
const std::vector<blink::SemanticsNode>& update) { | |||
const std::unordered_map<int32_t, blink::SemanticsNode>& update) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cant possibly compile. The argument is being iterated over and the pair wont contain the id
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe typedef
this to something and document the key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Which target uses this code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's the "content_handler". Can I build and test it on a Mac? I can't find anything about it in https://github.com/flutter/engine/blob/master/CONTRIBUTING.md.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking that the default Fuchsia target builds should be fine. https://fuchsia.googlesource.com/docs/+/HEAD/getting_started.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This look good now, right?
lib/ui/semantics/semantics_update.h
Outdated
@@ -23,18 +23,19 @@ class SemanticsUpdate : public fxl::RefCountedThreadSafe<SemanticsUpdate>, | |||
|
|||
public: | |||
~SemanticsUpdate() override; | |||
static fxl::RefPtr<SemanticsUpdate> create(std::vector<SemanticsNode> nodes); | |||
static fxl::RefPtr<SemanticsUpdate> create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static method names start with an uppercase letter. So Create(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not adding this method, just changing its signature. I'll happily do the clean-up, but I'd rather do that in a separate PR.
lib/ui/semantics/semantics_update.h
Outdated
|
||
std::vector<SemanticsNode> nodes_; | ||
std::unordered_map<int32_t, SemanticsNode> nodes_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document what the new key means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created type alias SemanticsNodeUpdates
and documented it.
@@ -8,11 +8,21 @@ | |||
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" | |||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" | |||
|
|||
#import <UIKit/UIKit.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C headers go above the non-system C++ headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -559,6 +559,10 @@ - (void)dealloc { | |||
[super dealloc]; | |||
} | |||
|
|||
- (FlutterTextInputView*)textInputView { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please ensure that the signatures match. UIKit docs say that this needs to be UIView*
. So lets keep that the same in both the header and implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" | ||
#include "lib/fxl/macros.h" | ||
#include "third_party/skia/include/core/SkMatrix44.h" | ||
#include "third_party/skia/include/core/SkRect.h" | ||
|
||
#import <UIKit/UIKit.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This goes above the non-system C++ headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* Direct children of this semantics object. Each child's `parent` property must | ||
* be equal to this object. | ||
*/ | ||
@property(nonatomic, readonly) std::vector<SemanticsObject*>* children; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make these readonly
properties const
. For example, I doubt it is safe for external accessor of this object to mutate the vector of children.
So this would be something like:
@property(nonatomic, readonly) const std::vector<SemanticsObject*>& children;
. If the vector itself can be nullptr, then you may use a pointer instead of a reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually SemanticsObject
uses a retained mode API. It is mutated in-place as the semantics tree is updated.
*/ | ||
@property(nonatomic, readonly) std::vector<SemanticsObject*>* children; | ||
|
||
- (BOOL)willCauseLayoutChange:(const blink::SemanticsNode*)node; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method name is not idiomatic Objective-C. -(BOOL)nodeWillCauseLayoutChange:...
works better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* | ||
* This class is used by `TextInputSemanticsObject`. | ||
*/ | ||
@interface InactiveTextInput : UIView<UITextInput> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no namespaces in Objective-C. So Flutter classes must have some sort of a prefix. So prepend FLT or Flutter to the Objective-C method name. @cbracken probably better knows the convention used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefixed with Flutter
, although I see we have a mix of names, some prefixed, others not. I'm guessing this namespace is not exported to developers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry - missed this patch earlier. Thanks for updating -- Flutter
is the prefix we use for all the iOS side work.
* | ||
* This class is used by `TextInputSemanticsObject`. | ||
*/ | ||
@interface InactiveTextInput : UIView<UITextInput> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the implementation of this class and it is not in a public header. Did you forget to push some changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look for changes in accessibility_bridge.mm
(GitHub collapsed it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing out the collapsed file. I added more comments around the leaking ivars that are synthesized implicitly. Please also add the concrete implementations to a separate file.
return YES; | ||
} | ||
|
||
@end | ||
|
||
@interface InactiveTextPosition : UITextPosition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put these in a separate file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
@end | ||
|
||
@implementation InactiveTextPosition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please explicitly synthesize all properties. Though the compiler will synthesize these properties for you, specifying the same makes the intent clearer and makes it obvious that the properties should be collected in dealloc in case ARC is not being used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not use ARC, so all the properties implicitly synthesized and set by callers during the lifetime of the object will be leaked when this object is collected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll attempt to remove these classes (see @goderbauer's suggestion to share these with the FlutterTextInputPlugin).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (removed these classes)
@property(nonatomic, readonly) shell::AccessibilityBridge* bridge; | ||
|
||
/** | ||
* The accessibility node used to produce this semantics object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The semantic nodes... ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@end | ||
|
||
/** | ||
* An implementation of `UITextInput` used for text fields that are not currently focused. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we specify the type of focus here (e.g. input focus here as opposed to accessibility focus)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
/** | ||
* An implementation of `SemanticsObject` specialized for expressing text fields. | ||
* | ||
* Uses `InactiveTextInput` and `FlutterTextInputView` to express blurred and focused |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same. We should be specific about the focus type (input vs. accessibility focus) here to avoid future confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -108,8 +106,6 @@ - (instancetype)init { | |||
return nil; | |||
} | |||
|
|||
#pragma mark - Designated initializers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this no longer true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A glitch in the matrix. Reverted.
return YES; | ||
} | ||
|
||
@end | ||
|
||
@interface InactiveTextPosition : UITextPosition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can we not reuse the TextPosition and TextRange from the active text input?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there every any danger that iOS asks us for a TextPosition or TextRange while the text field is unfocused (returning an InactiveTextPosition/Range) and then when the text field becomes focused iOS passes those InactiveTextPositions/Ranges back to the real text input view, which doesn't know what to do with them and potentially crashes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return [self.text substringWithRange:textRange]; | ||
} | ||
|
||
- (void)replaceRange:(UITextRange*)range withText:(NSString*)text { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add comments to the empty and placeholder implementations to indicate if they have been left blank intentionally or if filling them in is a TODO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if ([self node].HasFlag(blink::SemanticsFlags::kIsFocused)) { | ||
// The text input view must have a non-trivial size for the accessibility | ||
// system to send text editing events. | ||
[self bridge]->textInputView().frame = CGRectMake(0.0, 0.0, 1.0, 1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm (and maybe to add to the comment): The textInputView itself is not focusable directly by the user, right? It remains hidden even though it has a size now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. See the FlutterTextInputViewAccessibilityHider
class in 07501fc.
} | ||
|
||
- (UIAccessibilityTraits)accessibilityTraits { | ||
// Adding UIAccessibilityTraitKeyboardKey to the trait list so that iOS treat it like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
treat -> treats?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return [self textInputSurrogate].accessibilityTraits | UIAccessibilityTraitKeyboardKey; | ||
} | ||
|
||
- (CGPoint)accessibilityActivationPoint { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to move the activation point to the center? Isn't that the default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
#pragma mark - UIAccessibility overrides | ||
|
||
- (UIAccessibilityTraits)accessibilityTraits { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this implementation, we currently don't support text fields that at the same time want to be "checked" or "selected" or express any other accessibility trait other than being a text field.
If that has to be that way, we should at least document that the SemanticsFlag.isTextField on iOS is mutually exclusive with many other flags.
Or, could we just or in the other accessibility traits in the TextInputSemanticsObject?
In the PR's description under "What works" you list
Should this be moved to "What doesn't work" or should the "not" be removed from the bullet point? |
Also: Since the interactions here are fairly complicated, it would be sooo nice to have tests (especially to catch regressions). But setting up a test harness for this is probably outside of the scope of this PR... flutter/flutter#12287 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO:
- fix
content_handler
- move new classes into separate files
- share
TextRange
/TextPosition
impls - make sure
FlutterTextInputView
is not focusable
lib/ui/semantics/semantics_update.h
Outdated
@@ -23,18 +23,19 @@ class SemanticsUpdate : public fxl::RefCountedThreadSafe<SemanticsUpdate>, | |||
|
|||
public: | |||
~SemanticsUpdate() override; | |||
static fxl::RefPtr<SemanticsUpdate> create(std::vector<SemanticsNode> nodes); | |||
static fxl::RefPtr<SemanticsUpdate> create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not adding this method, just changing its signature. I'll happily do the clean-up, but I'd rather do that in a separate PR.
lib/ui/semantics/semantics_update.h
Outdated
|
||
std::vector<SemanticsNode> nodes_; | ||
std::unordered_map<int32_t, SemanticsNode> nodes_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created type alias SemanticsNodeUpdates
and documented it.
@@ -8,11 +8,21 @@ | |||
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" | |||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" | |||
|
|||
#import <UIKit/UIKit.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -559,6 +559,10 @@ - (void)dealloc { | |||
[super dealloc]; | |||
} | |||
|
|||
- (FlutterTextInputView*)textInputView { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" | ||
#include "lib/fxl/macros.h" | ||
#include "third_party/skia/include/core/SkMatrix44.h" | ||
#include "third_party/skia/include/core/SkRect.h" | ||
|
||
#import <UIKit/UIKit.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -108,8 +106,6 @@ - (instancetype)init { | |||
return nil; | |||
} | |||
|
|||
#pragma mark - Designated initializers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A glitch in the matrix. Reverted.
|
||
@end | ||
|
||
@implementation InactiveTextPosition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll attempt to remove these classes (see @goderbauer's suggestion to share these with the FlutterTextInputPlugin).
return [self.text substringWithRange:textRange]; | ||
} | ||
|
||
- (void)replaceRange:(UITextRange*)range withText:(NSString*)text { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
- (UIAccessibilityTraits)accessibilityTraits { | ||
// Adding UIAccessibilityTraitKeyboardKey to the trait list so that iOS treat it like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return [self textInputSurrogate].accessibilityTraits | UIAccessibilityTraitKeyboardKey; | ||
} | ||
|
||
- (CGPoint)accessibilityActivationPoint { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM for the accessibility side of things.
I defer to @cbracken and @chinmaygarde for the text input changes as well as general engine things.
|
||
#pragma mark - UIAccessibility overrides | ||
|
||
- (void)setSemanticsNode:(const blink::SemanticsNode*)node { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I believe this method and the next two are not really part of UIAccessibility protocol as indicated by the pragma above?
d7a4ef9
to
07501fc
Compare
blink::SemanticsNode node = nodeEntry->second; | ||
BOOL isTextField = node.HasFlag(blink::SemanticsFlags::kIsTextField); | ||
BOOL wasTextField = object.node.HasFlag(blink::SemanticsFlags::kIsTextField); | ||
if (wasTextField != isTextField) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe, the way this is set up we will only act correctly on a switch from textfield to non-textfield (and vice versa) if the parent of the switched node is included in the semantics update? If only the switched node is included in the semantics update, there seems to be nothing updating that node's parent's child list to include the new node?
Maybe, instead of holding on to child objects, we need to switch that to just ids? And whenever you need the real object you need to look it up in the objects_ map, which would be the ultimate truth?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I need to restructure this.
OTOH, why don't we include parents in the update though? Tree depth is O(log(N)) of the size of the tree, so omitting parent nodes doesn't save anything performance-wise. If we had parents with the update, we could update everything in a single depth-first pass. Also, it would remove the need for the objects_
map.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ideal case is that we have updates that send a single node only, so sending more nodes would be less good. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, assuming we don't lose elsewhere. For example, we currently pay for lack of parent information by having to maintain a fml::scoped_nsobject<NSMutableDictionary<NSNumber*, SemanticsObject*>> objects_
map that contains every single node in the tree (i.e. it's O(N) in size).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, we assume that every node included in the update has changed (and on Android we need to tell the OS about every node that has changed). If we now include unchanged nodes, we'd have to mark those in the update to avoid reporting unchanged nodes as changed...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of adding a SemanticsNodeUpdate
class that has a SemanticsNode
containing updated data. nullptr
would indicate "there no update to the node itself, only its children".
However, that's coming way too close to @chinmaygarde's proposal for a unified retained-mode semantics tree, so I'm not going to do this as part of this change, and just swap out the child reference using the current system. We can come back to this later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see 4fc35ac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update, after rebase it's now 5baa927
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nits but LGTM otherwise. Thanks!
@@ -65,7 +65,7 @@ class RuntimeHolder : public blink::RuntimeDelegate, | |||
std::string DefaultRouteName() override; | |||
void ScheduleFrame(bool regenerate_layer_tree = true) override; | |||
void Render(std::unique_ptr<flow::LayerTree> layer_tree) override; | |||
void UpdateSemantics(std::vector<blink::SemanticsNode> update) override; | |||
void UpdateSemantics(blink::SemanticsNodeUpdates update) override; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why copy the collection in this call and not pass it by reference instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize you did not add this call. So it fine for us to address this in a future patch.
lib/ui/semantics/semantics_node.h
Outdated
* The keys in the map are stable node IDd, and the values contain | ||
* semantic information for the node corresponding to the ID. | ||
*/ | ||
using SemanticsNodeUpdates = std::unordered_map<int32_t, SemanticsNode>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use javadoc/headerdoc format for docstrings in the engine. Lets follow the CPP guide for consistency go/fluttercpp#Function_Comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
_bridge = nullptr; | ||
_children.clear(); | ||
[_parent release]; | ||
if (_container != nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nil
check is unnecessary as calling the release selector on nil is a no-op already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
4fc35ac
to
5baa927
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Can you update flutter/flutter#12786 and/or file new bugs for the things that still don't work so we can track them?
5baa927
to
5f4033e
Compare
5f4033e
to
371e9b8
Compare
I will update the issues. |
`UIAccessibilityTraitKeyboardKey` was added in #4575 so that `TextInputSemanticsObject` supported VoiceOver gestures for text editing features, such as pinch to select text, and up/down fling to move cursor. After experimenting with it, I found that those features were still available even after removing `UIAccessibilityTraitKeyboardKey`. Fixes flutter/flutter#94465. In Touch Typing Mode: https://github.com/flutter/engine/assets/15619084/ccfe90ff-d3bc-427b-b1aa-9ec1242c0c89 In Standard Typing Mode: https://github.com/flutter/engine/assets/15619084/c78b1fb0-0816-41fb-9dd5-ed8b8a4cda2d [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This fixes many points from flutter/flutter#12786.
What works:
What doesn't work:
/cc @cbracken who implemented our iOS text entry system