Menu

#1612 Inline find can silently fail to scroll to a match inside table-structured content

Other
open-fixed
nobody
None
5
2026-07-24
2026-07-23
Alex Jpn
No

When the inline find bar (Cmd+F) locates a match, it computes where to scroll via PDFSelection -boundsForPage:. For text located inside certain table-structured PDF content, this method can return a degenerate rect — either an infinite origin with zero size, or an all-zero rect — instead of the match's real position. Skim then either scrolls nowhere (zero-size rect, nothing for goToRect: to act on) or scrolls to a nonsensical location. The result: the found text is highlighted internally, but the view never moves to show it.

This is not tied to how the search was anchored — it reproduces both:

  • when Skim falls back to its "reconstructed anchor" (an artificial whole-page selection used when there's no live currentSelection to search from), and
  • on a completely plain, unanchored search with no reconstruction involved at all.
    So the underlying defect is in how boundsForPage: computes geometry for this class of content generally, not something specific to any one search path.

Issue reproduced using PDFs containing tables generated by ReportLab, and also certain large technical PDFs generated using FrameMaker (probably others too).
A minimal PDF for reproduction is attached (find-scroll-bug-repro.pdf): single page, small table, target phrase widget alpha appearing twice — once near the top, once further down. Steps:

  • Cmd+F, search widget alpha — lands on the first occurrence correctly.
  • Shrink the window (or zoom in) so the second occurrence isn't currently visible.
  • Press Return again — the second occurrence is found (selection updates internally) but the view doesn't scroll to show it.

Proposed fix (tested, diff attached): If boundsForPage: comes back non-finite or empty, reconstruct the target rect from PDFPage -characterBoundsAtIndex: (a different, unaffected PDFKit code path) using the match's first/last character index — both already available via Skim's own safeIndexOfFirstCharacterOnPage:/safeIndexOfLastCharacterOnPage:. Falls back further to goToPage: (right page, not necessarily the right row) only if even that can't be determined.

1 Attachments

Discussion

  • Christiaan Hofman

    I cannot reproduce any of this. When I follow your steps it correctly scrolls to both matches. So it sounds more like a bug in your version of PDFKit. I don't see that it really is worthwhile to try to work around this bug in the way you describe, as I don't see why we then can expect the character bounds will be correct if the selection bounds is bogus, if not in this version of PDFKit or the next, given that we are talking about a bug. Also, what do you mean by a non-finite bounds, are you saying that components of the returned NSRect are NaN? I have never seen anything like that. I also don;'t see any diff attached.

     
  • Alex Jpn

    Alex Jpn - 2026-07-23

    Thanks. This is tested on Skim 1.7.15 with macOS Tahoe 26.5.2 (Apple Silicon).
    When testing with the provided pdf, did you reduce the window size so that no more than one of the instances of the world "alpha" are shown on the screen? In this case, when I click left and right arrows it does not move the page so that the selected instances are visible. Screenshot attached.
    Per debug log I tested with, the returned rect is CGRectNull, with origin components +Inf and size (0,0). The thinking is just to use character bounds as a fallback if selection bound retrieval fails - at least this addresses the scenario I found.
    Reattached the diff too for reference - although maybe a better check would be CGRectIsNull()

     

    Last edit: Alex Jpn 2026-07-23
  • Christiaan Hofman

    • status: unread --> open-fixed
     

Log in to post a comment.