Skip to content

fix(pdf-misc): do not signal from the size indication mode-line - #365

Open
alberti42 wants to merge 1 commit into
vedang:masterfrom
alberti42:fix/misc-size-indication-no-error
Open

fix(pdf-misc): do not signal from the size indication mode-line#365
alberti42 wants to merge 1 commit into
vedang:masterfrom
alberti42:fix/misc-size-indication-no-error

Conversation

@alberti42

Copy link
Copy Markdown

What happens

pdf-misc-size-indication is put into mode-line-position as an :eval construct, so it runs on every redisplay. When it signals, redisplay reports the error and drops the rest of the line:

Error during redisplay: (eval (pdf-misc-size-indication) t) signaled (wrong-type-argument overlayp nil)

Reverting a PDF while it is on screen — what AUCTeX does through TeX-revert-document-buffer when a recompile finishes — produced this two to six times per revert on a document with pdf-view-roll-minor-mode enabled.

Why

It calls pdf-view-image-size, which has nothing to measure whenever the page carries no image. With pdf-view-roll-minor-mode that function reads the overlay holding the page:

(overlay-get (pdf-roll-page-overlay page window) 'display)

so it signals rather than returning nothing. revert-buffer replaces the buffer text, and a page overlay carries evaporate, so the overlays collapse; until they are rebuilt every redisplay in that window reports the error.

The fix

Return an empty indication when the size is not available.

Guarding the read in pdf-view-image-size instead is not an option: some thirty-five callers across pdf-view.el, pdf-util.el, pdf-annot.el, pdf-links.el, pdf-sync.el and pdf-isearch.el do arithmetic on its result, so it cannot start returning nil. What that function should report when a page has no image yet is a separate question, and not one a mode-line construct needs answered — it just needs to not signal.

Normal reporting is unchanged: " Top" at the top of a page, " Bot" and the percentage below it.

Reproducing it

A one-shot advice that makes a revert land inside a page render. The lexical-binding cookie matters — without it the timer's lambda does not capture buf and win, and nothing happens. The revert also has to fire with a window other than the PDF's selected, which is what a revert from the TeX process sentinel does.

;; -*- lexical-binding: t; -*-
(defvar my-pdf-race-armed t)

(defun my-pdf-race (&rest _)
  (when my-pdf-race-armed
    (setq my-pdf-race-armed nil)
    (let* ((buf (current-buffer))
           (pdfwin (get-buffer-window buf t))
           (win (car (seq-remove (lambda (w) (eq w pdfwin))
                                 (window-list (window-frame pdfwin))))))
      (unless win (user-error "Split the PDF's frame first"))
      (run-at-time 0 nil
                   (lambda ()
                     (when (buffer-live-p buf)
                       (with-selected-window win
                         (with-current-buffer buf (revert-buffer t t)))))))))

(advice-add 'pdf-view-create-page :before #'my-pdf-race)

Open a PDF in a frame that has a second window, then M-x pdf-roll-goto-page to a page that has not been rendered yet, and read *Messages*. On a 16 page document the error appeared in two of two runs before this change and none of two after.

Priority

Lower than #361, #362 and #364. This is a cosmetic failure — noise in *Messages* and a briefly blank size indication — rather than a crash, and it corrects itself on the next redisplay.

It is also independent of all three: it touches only lisp/pdf-misc.el, and git merge-tree reports no conflict against any of them.

`pdf-misc-size-indication' runs from a mode-line construct, so it may not
signal: redisplay reports the error and drops the rest of the line.

    Error during redisplay: (eval (pdf-misc-size-indication) t) signaled
    (wrong-type-argument overlayp nil)

It calls `pdf-view-image-size', which has nothing to measure whenever the
page carries no image.  With `pdf-view-roll-minor-mode' that function
reads the overlay holding the page:

    (overlay-get (pdf-roll-page-overlay page window) 'display)

so it signals rather than returning nothing, and a `revert-buffer' that
collapses the overlays leaves a window in which every redisplay reports
the error until they are rebuilt.  Reverting a PDF while it is on screen
-- what AUCTeX does when a recompile finishes -- reproduced it two to six
times per revert.

Return an empty indication instead.  Guarding `pdf-view-image-size'
itself is not an option: some thirty callers do arithmetic on its result,
so it cannot start returning nil.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant