Skip to content

Implementing UIA provider for TextBox and MaskedTextBox controls#7741

Merged
Tanya-Solyanik merged 1 commit intodotnet:mainfrom
NikitaSemenovAkvelon:Issue_3421-Implementing_TextBox_UIA_Provider
Oct 5, 2022
Merged

Implementing UIA provider for TextBox and MaskedTextBox controls#7741
Tanya-Solyanik merged 1 commit intodotnet:mainfrom
NikitaSemenovAkvelon:Issue_3421-Implementing_TextBox_UIA_Provider

Conversation

@NikitaSemenovAkvelon
Copy link
Contributor

@NikitaSemenovAkvelon NikitaSemenovAkvelon commented Sep 6, 2022

Fixes #3421

Proposed changes

  • Enabled UIA provider for TextBox with nested classes and MaskedTextBox.
  • Refactored TextBox's child classes to reduce extra code.
  • Implemented IValueProvider for TextBoxBaseAccessibleObject.
  • Raised AutomationFocusChangedEvent in OnGotFocus methods.
  • Added few unit tests.

Customer Impact

  • Improving development experience for TextBox with nested classes and MaskedTextBox control accessibility.

Regression?

  • No

Risk

  • Minimal

Screenshots

Before

Screenshot 2022-09-06 090441
TextBox
Screenshot 2022-09-06 090506
MaskedTextBox

After

Screenshot 2022-09-06 085747
Screenshot 2022-09-06 090029
TextBox
Screenshot 2022-09-06 085948
Screenshot 2022-09-06 090049
MaskedTextBox

Test methodology

  • Manually
  • Accessibility tools
  • Unit tests
  • CTI

Accessibility testing

  • Inspect
  • AI
  • Narrator

Test environment(s)

  • 8.0.100-alpha.1.22423.9
Microsoft Reviewers: Open in CodeFlow

@NikitaSemenovAkvelon NikitaSemenovAkvelon requested a review from a team as a code owner September 6, 2022 05:54
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch 2 times, most recently from a97f295 to f1276a6 Compare September 6, 2022 10:13
@Tanya-Solyanik Tanya-Solyanik added this to the .NET 8.0 milestone Sep 7, 2022
dkazennov
dkazennov previously approved these changes Sep 8, 2022
Copy link
Contributor

@dkazennov dkazennov left a comment

Choose a reason for hiding this comment

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

As I understand in it's principle it is similar to other PRs to add UIA provider to controls (like #7314 I did).
Looks good to me.

Copy link
Contributor

@vladimir-krestov vladimir-krestov left a comment

Choose a reason for hiding this comment

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

Looks good, but should be carefully tested

Copy link
Contributor

@dmitrii-drobotov dmitrii-drobotov left a comment

Choose a reason for hiding this comment

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

Nice work! Did you also test that there are no memory leaks for accessible objects after your changes?

Comment on lines -2219 to -2222
if (@object is TextBoxBaseAccessibleObject accessibleObject)
{
accessibleObject.ClearObjects();
}
Copy link
Contributor

@dmitrii-drobotov dmitrii-drobotov Sep 12, 2022

Choose a reason for hiding this comment

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

The first case was removed because of UiaCore.UiaDisconnectProvider is called from another place.

It's called only when control has SupportsUiaProviders as true, but there is RichTextBox for which it's false. I'm not sure about all the details here, but RichTextBox could still somehow have an active AccessibilityObject for which we need to call UiaCore.UiaDisconnectProvider.

@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch 2 times, most recently from 12bc14f to 661b73e Compare September 13, 2022 06:17
Copy link
Contributor

@Tanya-Solyanik Tanya-Solyanik left a comment

Choose a reason for hiding this comment

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

Looks good, I added some comments, please see them. Had you compared the resulting provider set and properties to what is required by the docs https://docs.microsoft.com/windows/win32/winauto/uiauto-supporteditcontroltype?

=> Owner is TextBoxBase textBoxBase && textBoxBase.ReadOnly;
=> Owner is TextBoxBase { ReadOnly: true };

public override string? Name => Owner.AccessibleName ?? string.Empty;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does the base class implementation not work? TextBox should get AccessibleName from the label placed before it in the tab order. You dropped that part of the implementation. Maybe it does not make sense for the DGV cells, but it makes sense for other TextBoxes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I compared my implementation with MSAA behavior, the AccessibleName was empty. It was a reason why I implemented it that way. It was probably wrong and I've reworked it through the documentation above.

Copy link
Contributor

@dmitrii-drobotov dmitrii-drobotov Sep 20, 2022

Choose a reason for hiding this comment

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

I see that now accessible names match the TextBox content:
Accessibility Insights shows accessible names of TextBoxes which match its content

I don't think this is expected behavior because it makes Narrator announce the content twice:

TextBoxes window, Some long long text for a multiline TextBox that contains several lines with withspaces,tabs and numbers 12345, edit, Some long long text for a multiline TextBox that contains several lines with withspaces,tabs and numbers 12345,
Some long long text for a RTL TextBox, edit, Some long long text for a RTL TextBox,
Some long long text for a TextBox, edit, Some long long text for a TextBox,

If there is a label before TextBox then name will be filled from it — this functionality now works, but the default name should be empty. Also, check docs:

UIA_NamePropertyId — The name of the edit control is typically generated from a static text label. If there is not a static text label, a property value for Name must be assigned by the application developer. The Name property should never contain the textual contents of the edit control.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see this as an application problem that should be raised by the AccessibilityInsights for the app developer to fix. Framework does not know the business logic behind this text box and can't assign a meaningful name. As long as tooling raises the issue, we are good.

If there is a code path to keep Accessible Name empty , it would be a better fix, but I wouldn't spend much time on it (I think we have a property that controls it)

@Tanya-Solyanik Tanya-Solyanik added the waiting-author-feedback The team requires more information from the author label Sep 15, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from 661b73e to ed69ba3 Compare September 19, 2022 05:10
@ghost ghost removed the waiting-author-feedback The team requires more information from the author label Sep 19, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from ed69ba3 to 05e9131 Compare September 19, 2022 06:08
Copy link
Contributor

@Tanya-Solyanik Tanya-Solyanik left a comment

Choose a reason for hiding this comment

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

Please see the question about the RichTextBox

@Tanya-Solyanik Tanya-Solyanik added the waiting-author-feedback The team requires more information from the author label Sep 20, 2022
@ghost ghost removed the waiting-author-feedback The team requires more information from the author label Sep 20, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from 05e9131 to cc2a609 Compare September 20, 2022 04:29
Copy link
Contributor

@dmitrii-drobotov dmitrii-drobotov left a comment

Choose a reason for hiding this comment

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

Looks good! I also checked the accessibility docs for edit control and found some inconsistencies. For example:

If an edit control contains placeholder text (for example, a cue banner), the text should be used as the HelpText property unless the text can be edited by the user and then reused as placeholder text. For example, the Windows Internet Explorer address bar contains the text "about:Tabs" when a new tab is opened. This is not HelpText because it is a programmatic address that can be used or edited by the user.

We have the PlaceholderText property, so it's possible to set a placeholder, but the HelpText property won't be set, because it's not implemented in this PR. But what I found is that this functionality didn't work before, so this PR won't be a regression.

I didn't go through all the docs content but there is at least UIA_IsPasswordPropertyId with the same problem — it's not implemented in this PR but wasn't working before either. Should we fix all these inconsistencies in this PR or later as separate issues?

@Tanya-Solyanik
Copy link
Contributor

@dmitrii-drobotov - great findings! Yes, please open a new issue.

@Tanya-Solyanik
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@Tanya-Solyanik Tanya-Solyanik added the waiting-author-feedback The team requires more information from the author label Sep 20, 2022
Tanya-Solyanik
Tanya-Solyanik previously approved these changes Sep 27, 2022
Copy link
Contributor

@Tanya-Solyanik Tanya-Solyanik left a comment

Choose a reason for hiding this comment

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

Thank you! Please sent to the CTI team for testing if you had not done already.

@NikitaSemenovAkvelon NikitaSemenovAkvelon marked this pull request as draft September 27, 2022 11:33
@ghost ghost added the draft draft PR label Sep 27, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch 2 times, most recently from 1f003dd to ead1356 Compare September 28, 2022 08:15
@NikitaSemenovAkvelon NikitaSemenovAkvelon marked this pull request as ready for review September 28, 2022 09:31
@NikitaSemenovAkvelon
Copy link
Contributor Author

Fixed cases that CTI found.

@NikitaSemenovAkvelon NikitaSemenovAkvelon added waiting-review This item is waiting on review by one or more members of team and removed draft draft PR labels Sep 28, 2022
@ghost ghost added the waiting-author-feedback The team requires more information from the author label Sep 28, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from ead1356 to 067de2e Compare September 29, 2022 04:56
@ghost ghost removed the waiting-author-feedback The team requires more information from the author label Sep 29, 2022
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from 067de2e to 230b77f Compare September 29, 2022 11:01
@NikitaSemenovAkvelon NikitaSemenovAkvelon force-pushed the Issue_3421-Implementing_TextBox_UIA_Provider branch from 230b77f to cfe49c2 Compare September 30, 2022 04:23
@Tanya-Solyanik Tanya-Solyanik removed the waiting-review This item is waiting on review by one or more members of team label Oct 5, 2022
@Tanya-Solyanik Tanya-Solyanik merged commit 55b0586 into dotnet:main Oct 5, 2022
@ghost ghost modified the milestones: .NET 8.0, 8.0 Preview1 Oct 5, 2022
@MelonWang1
Copy link
Contributor

Verified this issue with latest .NET 8.0.100-alpha.1.22512.27, Add support UIA provider for TextBox and MaskedTextBox controls, screenshort as below:
Textbox:
inspect-textbox
ai-textbox

MaskedTextbox:
inspect-masktextbox
ai-masktextbox

v-elnovikova pushed a commit to v-elnovikova/winforms that referenced this pull request Oct 18, 2022
…net#7741)

Enabled UIA provider for TextBox with nested classes and MaskedTextBox.
Refactored TextBox's child classes to reduce extra code.
Implemented IValueProvider for TextBoxBaseAccessibleObject.
Raised AutomationFocusChangedEvent in OnGotFocus methods.
Added few unit tests.
@ghost ghost locked as resolved and limited conversation to collaborators Nov 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

waiting-for-testing The PR is awaiting manual testing by the primary team; no action is yet required from the author(s)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Epic - [Accessibility] Implement UIA provider for all controls

7 participants