Repository navigation
fix(snapshot): stop listing edit fields scrolled out of view at (0,0) - #616
Open
tanishqbaweja wants to merge 1 commit into
Open
tanishqbaweja wants to merge 1 commit into
tanishqbaweja wants to merge 1 commit into
Conversation
The tree walk's visibility check keeps edit fields even when UI Automation reports them off-screen, as it does for a field scrolled out of view: further down a web page, or below the bottom of a long form's window. tree_traversal() clips each element's box to its window (in a browser, to the page) and to the screen. Nothing of such a field is left, so its box became (0,0,0,0) and its center (0,0). A named field was still listed: Snapshot printed it as '(0,0) edit "Comment" [action: fill]', and Click or Type with its label went to the top-left corner of the primary display. Leave out an element whose clipped box is empty, as the IA2 walk and the word nodes already do. An element with any part on screen is listed as before, edits that UIA reports off-screen included.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
UIA reports an element that is scrolled out of view as off-screen, and a provider can still give its real position, past the edge of the view.
tree_traversal()drops off-screen elements, except edit fields and a browser's list items:So a text box further down a web page, or below the bottom of a long form's window, is taken as interactive.
iou_bounding_box()then clips its box to its window (in a browser, to the page) and to the screen. Nothing of it is left, so the box becomes(0,0,0,0)and the center(0,0), and a named field is still listed:(0,0) edit "Comment" [action: fill].get_coordinates_from_label()returns(0, 0)for its label, soClickandTypewith that label click the top-left corner of the primary display, andTypetypes there.#592 described this
(0,0)result for elements outside a stale screen box and fixed the stale box. Elements outside their own window or page still get it.Reproduction
At 106b50c on Windows 11 (build 22631) with Python 3.14.9, with mocks only. A script built two windows out of MagicMock UIA elements that hold the cached properties the walk reads: a Chrome window whose page (
RootWebArea) has a link "Sign in" and, further down, an edit "Comment" atRect(100, 1500, 700, 1530); and a "Settings" window at(0,0)-(800,600)with a button "OK" and an edit "Notes" atRect(100, 900, 700, 930), below the window. Both edits reportIsOffscreen. The script ran them through the realTree.get_state()andtree_traversal(), withControlFromHandle, the cache requests and the children lookup patched, and printed each label with the pointDesktop.get_coordinates_from_label()gives for it (whatClickandTypeuse forlabel=), thensemantic_tree_to_string(). Output onmain:Without
use_domthe Chrome window gives the same labels and tree.Fix
tree/service.py,tree_traversal(): before an element is taken as interactive, its box is clipped as it would be listed (to the page in a browser's DOM walk, else to the window, and to the screen). When nothing is left, the element is left out, as the IA2 walk (_record()intree/ia2.py) and the word nodes (_append_word_nodes()) already do. The reproduction then gives:(0,0)change. An element with any part on screen is listed as before, with the center of that part, including an edit that reportsIsOffscreenwhile its box is on screen.regionordisplayalready dropped it: the region filter drops empty boxes.Tests
New
TestTreeTraversal::test_field_scrolled_out_of_view_is_not_listed_at_the_originintests/test_tree_service.py, 2 cases (a window, and a page in a browser's DOM walk). A form holds two edits that reportIsOffscreen: "Name", on screen, and "Comment", below the window or the visible page. The walk is the realtree_traversal(), with the children lookup patched. Only "Name" is listed, at(210,30); in the window case the rendered tree has that one element.I ran each file on its own, in the project's environment:
On
mainboth new cases fail:assert [('Comment', '(0,0)'), ('Name', '(210,30)')] == [('Name', '(210,30)')](window) andassert [('Name', '(210,30)'), ('Comment', '(0,0)')] == [('Name', '(210,30)')](web page). On this branch the file passes: 52 passed, the 50 tests onmainand the 2 new cases. The other files pass onmainand on this branch with the same counts:test_tree_views.py(29 passed),test_tree_closed_window.py(4),test_tree_retry_backoff.py(3),test_tree_walk_z_order.py(3),test_uia_timeouts.py(17) andtest_tree_cache_utils.py(3). I did not run the whole suite.This merges cleanly with #614, which changes
get_nodes()in the same file; with both,tests/test_tree_browser_controls.py(3 passed) andtests/test_tree_service.py(52) pass.ruff checkis clean on the test file; ontree/service.pyit reports the two W293 lines thatmainhas (650 and 749 there, 650 and 762 here). Neither file is formatted onmain:ruff formatleaves the added lines as they are, and on the test file it shows only the hunk it shows onmain.Not tested
A real browser or app: everything ran against mocks. To check it on a real machine, open a page in Chrome or Edge with a labelled text box below the visible part (a sign-up form longer than the window, say) and call Snapshot. On
mainthe UI tree should list that box at(0,0)with[action: fill]; with this change it should not be listed until it is scrolled into view. An edit field scrolled out of view in a long desktop form should behave the same.