Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@chunhtai
Copy link
Contributor

To make the UITextInput work properly, its accessibilityElementsHidden must return NO.

This pr makes sure to toggle it on or off when it is focused. However, I am not sure if there will be any side effect when doing this. Will write test once we confirm this is what we want to do.

Fixes flutter/flutter#71885

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test exempt. See testing the engine for instructions on
    writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.
  • The reviewer has submitted any presubmit flakes in this PR using the engine presubmit flakes form before re-triggering the failure.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@chunhtai chunhtai requested a review from gaaclarke January 19, 2021 22:24
@chunhtai chunhtai requested a review from xster January 19, 2021 22:25
Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

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

Nice detective work. I can't think of why this wouldn't be an acceptable fix. My biggest concern would be that we could swipe to have voiceover announce a widget that should be hidden after showTextInput is called but before hideTextInput. I'd make sure that couldn't happen with manual testing.

Comment on lines 1118 to 1165
// mimic the semantics tree from Flutter. We want the text field to be represented as a
// `TextInputSemanticsObject` in that `SemanticsObject` tree rather than in this
// `FlutterTextInputView` bridge which doesn't appear above a text field from the Flutter side.
Copy link
Member

Choose a reason for hiding this comment

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

We should update this comment.

@property(nonatomic, readonly) CATransform3D editableTransform;
@property(nonatomic, assign) CGRect markedRect;
@property(nonatomic) BOOL isVisibleToAutofill;
@property(nonatomic) BOOL hidden;
Copy link
Member

Choose a reason for hiding this comment

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

This should be called something like accessibilityHidden.

@chunhtai
Copy link
Contributor Author

@gaaclarke thanks for reminding, this PR doesn't work, i am able to swipe to focus the FlutterTextInputView.

I couldn't find a way to be able to make voiceover respond to UITextInput event while keeping the FlutterTextInputView hidden from accessibility focus.

At this moment, I am thinking whether there is a way to point the TextInputSemanticsObject to the FlutterTextInputView

@chinmaygarde
Copy link
Member

@chunhtai: Based on your last comment, it looks like this PR is not quite ready to land. Is that accurate? Can we close it or mark it WIP?

@chunhtai chunhtai added the Work in progress (WIP) Not ready (yet) for review! label Jan 21, 2021
@chunhtai chunhtai changed the title unhide uitextinput when focused [WIP]unhide uitextinput when focused Jan 21, 2021
@chunhtai chunhtai removed the Work in progress (WIP) Not ready (yet) for review! label Jan 27, 2021
@chunhtai chunhtai changed the title [WIP]unhide uitextinput when focused unhide uitextinput when focused Jan 27, 2021
@chunhtai
Copy link
Contributor Author

I have revised this pr. Test will be added once we confirm we want to proceed with this fix

There are three fail-safes I added to the fluttertextinputview

  1. Add back the fluttertextinputview hider, This prevent fluttertextinputview from receiving swipping-to-focus
  2. Adds delay enable logic to fluttertextinputview. It is a known issue that the fluttertextinputview may receive focus when it is activated during screen changes. This delay makes sure the voiceover cannot find the fluttertextinputview while it try to find the new focus due to screen changes.
  3. fluttertextinputview will direct the focus back to the current active textfield if it ever receives focus. I added this fail-safe as the last resort. I have not able to focus the fluttertextinputview after adding the above two fail-safes, but i assumed it is still possible. If such unfortunate event happens, this will make sure the focus is not stuck at the fluttertextinputview.

@chunhtai chunhtai requested a review from gaaclarke January 27, 2021 19:51
@chunhtai
Copy link
Contributor Author

@gaaclarke @xster Can you take another look whether this is what we want to do? I will add more tests once we confirm that.

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

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

Jeez, this is hard to review. I understand it's a hack. Why did you choose 0.5s? If the problem we are trying to fix is the missing of the announcement of typed characters it seems like 0.5s could be ample time to miss a character.

// with a semantics update sent to the engine. The voiceover will focus
// the newly attached active view while performing accessibility update.
// This results in accessibility focus stuck at the FlutterTextInputView.
[NSTimer scheduledTimerWithTimeInterval:_kUITextInputAccessibilityEnablingDelaySeconds
Copy link
Member

Choose a reason for hiding this comment

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

This causes the plugin to live beyond the point it would be dealloc'd previously. If you do this you should maintain a reference to the timer and invalidate it in dealloc.

Comment on lines 544 to 550
+ (UIAccessibilityElement*)backingTextInputAccessibilityObject {
return _backingTextInputAccessibilityObject;
}

+ (void)setBackingTextInputAccessibilityObject:(UIAccessibilityElement*)element {
_backingTextInputAccessibilityObject = element;
}
Copy link
Member

Choose a reason for hiding this comment

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

There is no need to make these methods, this should just be a property.

Comment on lines +1151 to +1150
* There are other cases the `FlutterTextInputView` may receive
* focus. One example is during screen changes, the accessibility
* tree will undergo a dramatic structural update. The Voiceover may
* decide to focus the `FlutterTextInputView` that is not involved
* in the structural update instead. If that happens, the
* `FlutterTextInputView` will make a best effort to direct the
* focus back to the `SemanticsObject`.
Copy link
Member

Choose a reason for hiding this comment

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

Couldn't this result in duplicate Voiceover announcements? One for the FlutterTextInputView and one SemanticsObject?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that is true, that is why i put the first two fail safe and hope it can catch all of the corner cases.

If this text view does receive the focus, duplicate announcement is still much better than focus just stuck at this textview.

I have tried a number of different hack such as changing the trait and label of this text view to prevent voiceover from pronouncing any word when the text view is focused, but none of them work. If you have a textview without any trait or label, it will pronounce some random phrase such as "blue sky" when it is focused.

// with a semantics update sent to the engine. The voiceover will focus
// the newly attached active view while performing accessibility update.
// This results in accessibility focus stuck at the FlutterTextInputView.
[NSTimer scheduledTimerWithTimeInterval:_kUITextInputAccessibilityEnablingDelaySeconds
Copy link
Member

Choose a reason for hiding this comment

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

The proper constant name in objective-c doesn't have a _ at the beginning.

@chunhtai
Copy link
Contributor Author

chunhtai commented Jan 27, 2021

Jeez, this is hard to review. I understand it's a hack. Why did you choose 0.5s? If the problem we are trying to fix is the missing of the announcement of typed characters it seems like 0.5s could be ample time to miss a character.

I apologize for putting out such confusing workaround. I couldn't find a more systematic wait for delay this enable. The 0.5s is an eye ball value. we can probably decrease it even more, but overall do you think this is something we want to do?

Another idea is that we can wait until we detect any flutter semantics object has received focus before we enable the text view, but it will be much bigger than 0.5s.

@chunhtai
Copy link
Contributor Author

chunhtai commented Feb 1, 2021

@gaaclarke Hi 0.5 seems to be the lowest possible timeout; otherwise, the may still focus the textfield. I am not sure if this is device specific, but if the other low end iOS device can still focus textfield with 0.5 delay, they will be caught in fail safe 3.

@chunhtai chunhtai added the Work in progress (WIP) Not ready (yet) for review! label Feb 1, 2021
@chunhtai chunhtai changed the title unhide uitextinput when focused [WIP]unhide uitextinput when focused Feb 1, 2021
@chunhtai
Copy link
Contributor Author

chunhtai commented Feb 1, 2021

I will do some more clean up, but i think this is the best we can do for now.

@chunhtai chunhtai removed the Work in progress (WIP) Not ready (yet) for review! label Feb 3, 2021
@chunhtai chunhtai changed the title [WIP]unhide uitextinput when focused unhide uitextinput when focused Feb 3, 2021
@chinmaygarde
Copy link
Member

@gaaclarke Does your previous approval need to be revised? If so, can you review again please?

Comment on lines 1178 to 1179
NSTimer* _enableFlutterTextInputViewAccessibilityTimer;

Copy link
Member

Choose a reason for hiding this comment

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

This is a global variable as written, you need to put this in braces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops nice catch. will update

- (void)removeEnableFlutterTextInputViewAccessibilityTimer {
if (_enableFlutterTextInputViewAccessibilityTimer) {
[_enableFlutterTextInputViewAccessibilityTimer invalidate];
_enableFlutterTextInputViewAccessibilityTimer = nil;
Copy link
Member

Choose a reason for hiding this comment

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

This is a leak, sorry i didn't see it earlier. You need to retain this below, and release this here.

- (void)dealloc {
[self hideTextInput];
[_reusableInputView release];
[_inputHider release];
Copy link
Member

Choose a reason for hiding this comment

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

there needs to be [_enableFlutterTextInputViewAccessibilityTimer release] as well =)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that will be trigger by hideTextInput, my thinking is that the timer is created in showtextinput, so it should be removed in hidetextinput

Copy link
Member

Choose a reason for hiding this comment

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

Yea, I think in practice you are right since the timer will retain the FlutterTextInputPlugin until the timer fires.

if (_activeView.isFirstResponder) {
_activeView.accessibilityEnabled = YES;
}
_enableFlutterTextInputViewAccessibilityTimer = nil;
Copy link
Member

Choose a reason for hiding this comment

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

there needs to be a release here... maybe it would just be easier if you used a property for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for reminding.

@chunhtai chunhtai added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Feb 9, 2021
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Mac iOS Engine has failed. Please fix the issues identified (or deflake) before re-applying this label.

@fluttergithubbot fluttergithubbot removed the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Feb 9, 2021
@chunhtai chunhtai added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Feb 9, 2021
@fluttergithubbot fluttergithubbot merged commit b3a18f5 into flutter:master Feb 9, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Feb 10, 2021
@yasargil
Copy link

Can i request that this change get cherry picked into the 1.26 release?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes platform-ios waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VoiceOver occasionally doesn't announce typed characters/numbers in input fields

6 participants