Don't filter out MSAA events for the currently focused object, even if the winEvent limit has been exceeded for that thread#11520
Conversation
…ntly focused object, even if the winEvent limit has been exceeded for that thread.
See test results for failed build of commit e941b52f9f |
…bjects is now optional.
LeonarddeR
left a comment
There was a problem hiding this comment.
How about applications that fire lots of erroneous events on the focus object itself? They would no longer be ignored, right?
Rather than allowing all events for the focus object, have you considered applying a multiplier to MAX_WINEVENTS_PER_THREAD for allowed objects, or a separate counter for every allowed object?
| continue | ||
| if not alwaysAllowedObjects or k[1:-1] not in alwaysAllowedObjects: | ||
| threadCount = threadCounters.get(k[-1], 0) | ||
| threadCounters[k[-1]] = threadCount + 1 |
There was a problem hiding this comment.
A suggestion: May be an allowed object, while events for it should be allowed, yet should increase the counter. This ensures that focus event floading will block other events.
|
When events are added to the limitor, they are stored in a dictionary,
therefore there will only ever be one event of a particular eventID and
winEvent params. Thus, For a specific object, it would be very hard for
an app to flood us. They would essentially need to fire one of every
registered event type, which is highly unlikely.
We could perhaps give events for the focus object their own max of 10 I
guess...
|
…d still go up if the event is for the focus, even though we won't drop the event if we are over the limit.
LeonarddeR
left a comment
There was a problem hiding this comment.
Looks good to me now.
|
It's possible this PR fixes #10484. |
|
Google has been trying to fix this on their end as well. See chromium/chromium@a2e28ea#diff-2b5622f887b43b804657e10e077be787 |
feerrenrut
left a comment
There was a problem hiding this comment.
Thanks for taking this on @michaelDCurran. Looks like like it is pretty close.
| return True | ||
|
|
||
| def flushEvents(self): | ||
| def flushEvents(self, alwaysAllowedObjects=None): |
There was a problem hiding this comment.
Could you please add tests for this to tests.unit.test_orderedWinEventLimiter.TestOrderedWinEventLimiter
Should this check for None in tuple elements? A test to show what is expected in this case would be good.
Please also add typing information for alwaysAllowedObjects. It seems to be:
Optional[List[Tuple[
int, # windowHandle
int, # objectID
int, # childID
]]]
You could define a reusable type (that can be used in source/IAccessibleHandler/__init__.py also:
| def flushEvents(self, alwaysAllowedObjects=None): | |
| AllowedObjectType = Tuple[ | |
| int, # windowHandle | |
| int, # objectID | |
| int, # childID | |
| ] | |
| def flushEvents(self, alwaysAllowedObjects: Optional[List[AllowedObjectType]] = None): |
There was a problem hiding this comment.
Should this check for None in tuple elements? A test to show what is expected in this case would be good.
I don't understand what you mean here. Do you mean if one of the elements in one of the tuples is None? E.g. windowHandle is None? In that case, specific events would simply not match on that (poorly defined) object...
There was a problem hiding this comment.
Do you mean if one of the elements in one of the tuples is None?
Yes, one or more.
In that case, specific events would simply not match on that (poorly defined) object...
That's fine. A test helps to document that it is an expected arg value, and the behavior in this case is intentional.
I got thinking about this because of this line:
nvda/source/IAccessibleHandler/__init__.py
Line 868 in 1d5e5ce
See test results for failed build of commit 90d327b48b |
dc89550 to
68375d2
Compare
See test results for failed build of commit 07d6218bd8 |
…flushEvents and improve logic readability around skipping events due to exceeded count per thread.
7316138 to
1d5e5ce
Compare
|
It looks like tests were added and then removed. I assume this is being worked on right now, so I'll come back to review it later. Please re-request a review when it's ready. 😄 |
|
I have added several tests, but there was some surprising behavior. @michaelDCurran can you take a look at these please? |
… emitted now, not 11.
… error for events per thread, and no longer expect certain failures
|
|
||
| for n in range(500): # exceed the limit for a single thread | ||
| eventId = nonSpecialCaseEvents[n % len(nonSpecialCaseEvents)] | ||
| # same thread, different object. Use a second object to aid tracking. |
There was a problem hiding this comment.
I don't get this comment. Perhaps it was incorrectly copied from another method? source is hardcoded to (2,2,2) in this case. I.e. always the same object.
See test results for failed build of commit cfd3f6e676 |
|
@feerrenrut There was an off-by-one error for threadCount in OrderedWinEventLimiter. I have fixed this, so now 10 events (not 11) are now emitted. I was then able to remove the expectedFailure decorators off the tests. However, I did need to fix a couple of the other tests, that seemed to have hardcoded the assumption about 11. |
| # equal to MAX_WINEVENTS_PER_THREAD=10 | ||
| # Plus 4 focus events, | ||
| # Plus the last menu event. | ||
| # All totalling 15. | ||
| self.assertEqual(len(windowIds), 15) |
| # Two Foreground events, because they are added to multiple queues. | ||
| # Added to both _focusEventCache and _genericEventCache | ||
| # See also test_limitEventsPerThread | ||
| (winUser.EVENT_SYSTEM_FOREGROUND, *allowedSource), | ||
| (winUser.EVENT_SYSTEM_FOREGROUND, *allowedSource), |
There was a problem hiding this comment.
I think it would be good to create a new "good first issue" to address this. The tests mean it is fairly well defined, the intent is easy to understand, and is unlikely to require a big change.
Link to issue number:
None.
Summary of the issue:
If an app floods NVDA with a lot of MSAA events and therefore NVDA starts ignoring events due to the winEvent limit for that thread being exceeded, important MSAA events for the currently focused object may be ignored.
An example of this is on https://drive.google.com in Google Chrome:
Press gn to go to the navigation treeview.
When pressing right and left arrow to expand / collapse particular directories in the tree, NVDA may fail to announce the expanded / collapsed state, if the directory contains a lot of subdirectories.
Google Chrome seems to fire a great deal of locationChange, stateChange, show and hide events for the subdirectories. And because of this, the important stateChange event on the focused item is dropped by NVDA.
Description of how this pull request fixes the issue:
Testing performed:
Expanded and collapsed a large directory in the drive.google.com navigation tree, ensuring that NVDA announced the expand / collapsed state, where as before this change it did not.
Known issues with pull request:
None.
Change log entry:
Bug fixes: