-
-
Notifications
You must be signed in to change notification settings - Fork 21
Fix CI: add missing CaretGeometrySelector type referenced by tests #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import CoreGraphics | ||
| import Foundation | ||
|
|
||
| /// Pure caret-geometry trust policy used by `FocusSnapshotResolver`. | ||
| /// | ||
| /// Two decisions live here, kept free of live Accessibility objects so they can be unit tested: | ||
| /// 1. `shouldSearchDeep` — whether the focused input's own caret geometry is too weak to trust, | ||
| /// so the resolver should run the expensive deep AX-tree walk for a better source. | ||
| /// 2. `select` — given the primary candidate's geometry and an optional deep-walk result, which | ||
| /// rect to actually ship, following a fixed precedence. | ||
| /// | ||
| /// The regression these protect against is trusting a descendant rect over the focused input's own | ||
| /// usable rect (or vice versa). Chrome's AXTextArea answers BoundsForRange with a multi-line union | ||
| /// rect — labelled `.derived` but unusable for precise caret placement — while the leaf AXStaticText | ||
| /// holding the active line carries a real `.exact` rect that the deep walk can recover. | ||
| enum CaretGeometrySelector { | ||
| /// The caret geometry chosen to ship, plus a human-readable source label for diagnostics. | ||
| struct Selected: Equatable { | ||
| let rect: CGRect | ||
| let source: String | ||
| let quality: CaretGeometryQuality | ||
| let observedCharWidth: CGFloat? | ||
| } | ||
|
|
||
| /// Whether the primary (focused-input) caret geometry is too weak to trust, so the resolver | ||
| /// should run the deep AX-tree walk for a more precise source. | ||
| /// | ||
| /// `.exact` and `.derived` are trusted as-is; only `.estimated`, unknown quality, or a missing | ||
| /// rect justify the ~200-node walk. The walk pins a CPU core when run on every keystroke, so we | ||
| /// avoid it whenever the primary geometry is already good enough. | ||
| static func shouldSearchDeep( | ||
| primaryRect: CGRect?, | ||
| primaryQuality: CaretGeometryQuality? | ||
| ) -> Bool { | ||
| guard primaryRect != nil else { | ||
| return true | ||
| } | ||
| switch primaryQuality { | ||
| case .exact, .derived: | ||
| return false | ||
| default: | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| /// Chooses the caret geometry to ship from the primary candidate and the optional deep-tree | ||
| /// result. Returns `nil` when neither source produced a rect, which the caller maps to an | ||
| /// unsupported snapshot. | ||
| /// | ||
| /// Precedence: | ||
| /// 1. primary `.exact` (single API call, perfect — no walk needed) | ||
| /// 2. primary `.derived` (trusted; `shouldSearchDeep` skips the walk entirely for it) | ||
| /// 3. deep (any) (only reached when primary is `.estimated`/unknown) | ||
| /// 4. primary (any, fallback) | ||
| static func select( | ||
| primaryRect: CGRect?, | ||
| primaryQuality: CaretGeometryQuality?, | ||
| primaryObservedCharWidth: CGFloat?, | ||
| deepResult: CaretGeometryResult? | ||
| ) -> Selected? { | ||
| if let primary = primaryRect, primaryQuality == .exact { | ||
| return Selected( | ||
| rect: primary, source: "exact primary", quality: .exact, | ||
| observedCharWidth: primaryObservedCharWidth | ||
| ) | ||
| } | ||
| if let primary = primaryRect, primaryQuality == .derived { | ||
| return Selected( | ||
| rect: primary, source: "derived primary", quality: .derived, | ||
| observedCharWidth: primaryObservedCharWidth | ||
| ) | ||
| } | ||
| if let deep = deepResult { | ||
| return Selected( | ||
| rect: deep.rect, source: "\(deep.quality.label) deep", quality: deep.quality, | ||
| observedCharWidth: deep.observedCharWidth | ||
| ) | ||
| } | ||
| if let primary = primaryRect { | ||
| return Selected( | ||
| rect: primary, | ||
| source: "\(primaryQuality?.label ?? "unknown") primary-fallback", | ||
| quality: primaryQuality ?? .estimated, | ||
| observedCharWidth: primaryObservedCharWidth | ||
| ) | ||
| } | ||
| return nil | ||
| } | ||
| } | ||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 13–15 say Chrome's AXTextArea labels its multi-line union rect
.derived, it is "unusable for precise caret placement," and "the deep walk can recover" a real.exactrect from the leafAXStaticText. ButshouldSearchDeepnow returnsfalsefor.derived, andselectprefers primary.derivedover a deep.exact(seetestPrimaryDerivedWinsOverDeepExact). The protection described in the header is exactly the behavior this PR removes. A Chrome user with a.derivedprimary union rect will get that unusable rect shipped; the deep walk that recovered the leaf's.exactno longer fires.Either the doc is stale (Chrome's
.derivedgeometry is now actually usable) and the comment should be updated or removed, or the code regresses Chrome caret placement for editors that still expose a wide union rect under.derived.