Skip to content

Fix table navigation commands through merged cells by caching last column/row index#13345

Merged
seanbudd merged 15 commits into
masterfrom
fixTableNavigationPreserveRowColumn-2
Mar 25, 2022
Merged

Fix table navigation commands through merged cells by caching last column/row index#13345
seanbudd merged 15 commits into
masterfrom
fixTableNavigationPreserveRowColumn-2

Conversation

@seanbudd

@seanbudd seanbudd commented Feb 16, 2022

Copy link
Copy Markdown
Member

Follow up on the work done by @mltony in #11923

The approach is the same, just that types are added and a dataclass is used to cache the selection.

Link to issue number:

Fixes #7278, #11919

Summary of the issue:

When issuing table navigation commands repeadetly, e.g. pressing Control+Alt+Down several times in a row, the original column index is currently not preserved. Thus, if there happens to be a merged cell on the way, the column index will be reset to the minimal column index of merged cell.

Description of how this pull request fixes the issue:

This PR caches original column index for vertical table navigation and original row index for horizontal table navigation.

Testing strategy:

Known issues with pull request

Change log entries:

Bug fixes

- The cursor does not switch row or column anymore when using table navigation to navigate through merged cells. (#7278)

Code Review Checklist:

  • Pull Request description:
    • description is up to date
    • change log entries
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • API is compatible with existing add-ons.
  • Documentation:
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English

@seanbudd seanbudd changed the title Fix table navigation preserve row column 2 Fixing table navigation commands by caching last column/row index Feb 16, 2022
@seanbudd seanbudd marked this pull request as ready for review February 16, 2022 06:15
@seanbudd seanbudd requested a review from a team as a code owner February 16, 2022 06:15
Comment thread source/documentBase.py Outdated
Comment thread source/documentBase.py Outdated
Comment thread source/documentBase.py Outdated
Comment thread source/documentBase.py Outdated
Comment thread source/documentBase.py Outdated

def _getNearestTableCell(
self,
tableID,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is the type of this?

@seanbudd seanbudd Feb 16, 2022

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not sure, it's not documented anywhere. I spent some time investigating and couldn't get a clear idea. As the change/type is unrelated and no information is lost, I'm hesitant to spend too long investigating this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I had a quick look. In virtual buffers it is an int, whereas in UIA it is a tuple (the runtime id). I guess it's safe to mark it any, as long as it can be compared.

Suggested change
tableID,
# At least known to be a tuple for UIA and an integer for virtual buffers
tableID, typing.Any,

@seanbudd seanbudd Feb 16, 2022

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added a type and summary to the module level, as tableID is used as a parameter elsewhere in the file, and will need to get type information added eventually.

@seanbudd seanbudd changed the title Fixing table navigation commands by caching last column/row index Fix table navigation commands through merged cells by caching last column/row index Feb 16, 2022
@AppVeyorBot

This comment was marked as off-topic.

@CyrilleB79

Copy link
Copy Markdown
Contributor

Thanks @seanbudd to take over this PR.

I have not tested the snapshot of the current PR. But I have some points to add here:

  1. As explained in Fixing table navigation commands by caching last column/row index #11923 (comment) in the original PR, the issue was also present in Word tables. Is it fixed in this PR?
  2. Regarding the change log, I would have avoided the term "index" which is known by web developers, but maybe not by all users. What about this one:
    The cursor does not switch row or column anymore when using table navigation to navigate through merged cells. (#7278)
    Feel free to modify this further; I do not speak natively English.

@seanbudd

Copy link
Copy Markdown
Member Author

Thanks @CyrilleB79, that changelog entry reads fine for me, I've updated the PR description.

I haven't tested with Word yet, however this PR uses the same approach as in #11923, so if the issue was present in Word with #11923, this is still the case.

@seanbudd

Copy link
Copy Markdown
Member Author

@CyrilleB79 - It appears that the behaviour is fixed with MS Word as well now. This did need the latest master merged in to work with MS word, I think due to a related fix for table navigation in MS word.

@CyrilleB79

Copy link
Copy Markdown
Contributor

@seanbudd, no it is not completely fixed for MS Word; it behaves the same way as NVDA 2021.3.1.

More generally, I think that the table nav experience should be consistent between all the applications.
Under Word, I have created a 4x4 table, have filled the cell content with the cell's coordinates (as per Excel naming convention) and merged the following groups of cells:

I have tested navigating the whole table horizontally, then vertically in either direction.

Table navigation is as expected in the html file (with Chrome).

For Word document I get the following issues:

  • C2+D2, move right arrow. Expected: "Table edge" reported. Actual: D1
  • A4, right, left. Actual C4, A4. Expected B3+B4, A4.
  • B3+B4, down. Actual: A4. Expected "Table edge" reported.
  • D1, down, up. Actual: D3, D1. Expected: C2+D2, D1.

For PDF document, I get the following issue:

  • A3, down. Expected: A4. Actual: empty cell.
  • A4, left. Expected: "Table edge" reported. Actual: empty cell.
  • A4, right, left. Actual C4, A4. Expected B3+B4, A4.
  • B3+B4, down. Actual: A4. Expected "Table edge" reported.
  • D1, down. Actual: "Table edge" reported. Expected: C2+D2
  • D3, up. Actual: "Table edge" reported. Expected: C2+D2

It makes a lot of issues, but many of them are probably related to each other.

@mltony

mltony commented Feb 21, 2022

Copy link
Copy Markdown
Contributor

@seanbudd, first of all thanks for taking over this PR!
@CyrilleB79, I tried to repro your use cases with this PR. For some reason I couldn't reproduce your issues in MS Word. In focus mode it works all as expected for me.
One interesting observation though is that it doesn't appear to work in MS Word in browse mode, that is behavior with merged cells is exactly the same as before this PR, that is it never reuses cached row/column index in merged cells. I spent a little time debugging and found out that UIABrowseModeDocumentTextInfo class doesn't have eq method implemented, and so Python defaults to identity eq, which results to the following:

focus.treeInterceptor.selection == focus.treeInterceptor.selection
False
We rely on comparing selections to check whether user has moved away when the cache should be invalidated, so we're having a false positive here always. It should be easy to fix though. UIABrowseModeDocumentTextInfo inherits from RootProxyTextInfo, and it appears to be a thin wrapper around another TextInfo class and eq and hash methods should be forwarded to the nested textInfo there. I actually tried to fix this myself but ran into issues with tooling.
As for PDF problems, I actually wouldn't get into this territory. PDF format has a long list of accessibility issues and in this case most likely word has produced a malformed table in PDF or something.

@seanbudd

Copy link
Copy Markdown
Member Author

@seanbudd, first of all thanks for taking over this PR! @CyrilleB79, I tried to repro your use cases with this PR. For some reason I couldn't reproduce your issues in MS Word. In focus mode it works all as expected for me. One interesting observation though is that it doesn't appear to work in MS Word in browse mode, that is behavior with merged cells is exactly the same as before this PR, that is it never reuses cached row/column index in merged cells. I spent a little time debugging and found out that UIABrowseModeDocumentTextInfo class doesn't have eq method implemented, and so Python defaults to identity eq, which results to the following:

focus.treeInterceptor.selection == focus.treeInterceptor.selection
False
We rely on comparing selections to check whether user has moved away when the cache should be invalidated, so we're having a false positive here always. It should be easy to fix though. UIABrowseModeDocumentTextInfo inherits from RootProxyTextInfo, and it appears to be a thin wrapper around another TextInfo class and eq and hash methods should be forwarded to the nested textInfo there. I actually tried to fix this myself but ran into issues with tooling.
As for PDF problems, I actually wouldn't get into this territory. PDF format has a long list of accessibility issues and in this case most likely word has produced a malformed table in PDF or something.

This will only fix the problem if UIA is enabled. I'm not sure of way to compare the selection (TextInfos for a BrowseModeDocumentTextInfo).

@seanbudd seanbudd marked this pull request as draft February 21, 2022 02:08
@seanbudd

Copy link
Copy Markdown
Member Author

To fix the UIA case, UIABrowseModeDocumentTextInfo should inherit (at least eq and hash) from UIATextInfo.

@mltony

mltony commented Feb 27, 2022

Copy link
Copy Markdown
Contributor

@seanbudd, I fixed the word issue in #13396.

@seanbudd seanbudd marked this pull request as ready for review February 28, 2022 02:39
…reserveRowColumn-2

# Conflicts:
#	tests/system/robot/chromeTests.py
#	tests/system/robot/chromeTests.robot
@seanbudd

seanbudd commented Feb 28, 2022

Copy link
Copy Markdown
Member Author

I've reopened this PR, so that the remaining bug can be fixed in a separate PR eg #13396

@AppVeyorBot

This comment was marked as off-topic.

michaelDCurran pushed a commit that referenced this pull request Mar 17, 2022
… class UIABrowseModeDocumentTextInfo comparable (#13396)

PR #13345 fixes navigating over merged cells in tables by caching the last column/row. Testing showed that it doesn't work in MS Word while in browse mode (focus mode works fine). This was tracked down to class UIABrowseModeDocumentTextInfo not implementing eq method.

Description of how this pull request fixes the issue:
Fixing that by implementing eq and hash functions in parent class RootProxyTextInfo.
@feerrenrut feerrenrut added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label Mar 18, 2022
Comment thread source/documentBase.py


_TableID = Union[int, Tuple, Any]
"""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have never seen this pattern of an unnamed string following an assignment statement. Is it supposed to become the symbol's docstring? I'm not sure that actually works?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

epydoc supports this, however I have discovered it is bad practice, and part of the rejected PEP 224.

It appears the correct pattern for this in future is typing.Annotated in python 3.9.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We have been using this pattern already in some contexts such as BACK_COMPAT_TO, appModuleHandler.helperLocalBindingHandle.

@seanbudd seanbudd merged commit 44b16a1 into master Mar 25, 2022
@seanbudd seanbudd deleted the fixTableNavigationPreserveRowColumn-2 branch March 25, 2022 02:27
@nvaccessAuto nvaccessAuto added this to the 2022.2 milestone Mar 25, 2022
michaelDCurran pushed a commit that referenced this pull request Apr 20, 2022
Intermittent GC error "unreachable objects" caused by PR #13345.

Description of how this pull request fixes the issue:
The root cause was that we used to store TextInfo object inside Document, thus creating a cyclic reference. Such reference loops cannot be deleted by zeroing reference counter and can only be deleted by full GC sweep. I am not sure why NVDA prints warnings in this case.
This was fixed by not storing TextInfo in the first place. We now store last cell coordinates as lastRow/lastCol. Table cache is going to be valid as long as row/col of current selection are the same as stored lastRow/lastCol - and in this case we will be using trueRow/trueCol to compute next cell to preserve coordinates when navigating through merged cells.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Table navigation doesn't respect colspan

8 participants