What is going on with pgfpages and page labels?

I’m using a feature of beamer that shows notes beside slides, but the page numbers that are coming out are crazy, making it impossible to extract specific slides into other documents with \includegraphics[page=n]{presentation.pdf}.

For example, in this MWE, there are two frames that are each 1 slide, and then one frame that is four slides. The PDF page labels that show up in Acrobat are, as indicated, 2, 3, 3, 3, 3, and 7. It starts at page 2 instead of 1, and then there are four page 3s, but they don’t even all belong to the same frame!

\documentclass{beamer}
\usepackage{pgfpages}

\setbeameroption{show notes on second screen=left}
\def\pg#1{pgfpages says this is page #1 but it is really page \arabic{page}}

\begin{document}

\setcounter{page}{0}

\frame{hi \note{\pg{2}}}

\frame{there \note{\pg{3}}}

\frame{how \pause are \pause you \pause today
\note<1-3>{\pg{3}}
\note<4>{\pg{7}}}

\end{document}


Here’s what the output looks like:

I know that the manual says, “pgfpages will produce wrong page numbers in the .aux file” and gives a manual workaround. But the page counter still works, so shouldn’t there be some way to pass that through to the PDF? I’d like to fix this, but don’t know where to start. Specifically, when the manual says that “TeX instantiates the page numbers when writing an .aux file only when the physical page is shipped out,” what exactly is it talking about? Where is the source code for that?

-
As a hack until a proper fix/workaround is found, how about using \documentclass[hyperref={pdfpagelabels=false}]{beamer}, so then the PDF viewer has to display the actual page numbers rather than the one pgfpages appears to use. – cyberSingularity Jan 7 '13 at 0:31

The page labels in the .pdf file are actually independent of the page numbers in the .aux file. The page labels are also set during shipout but by the hyperref package.

The pgfpages package however ships out a physical page after the next/following logical page is finished. This is necessary for the 'two screens with optional second' layout to allow setting the second screen after the main screen. However, as a side effect, the page counter and some page states of the hyperref package (like page transition) are already set for the next logical page when the (previous) physical page is shipped, which results in the wrong pdfpagelabels and page transitions occurring too early.

To solve this problem, the relevant page states can be saved when the first logical page of a physical page is to be shipped and restored before the corresponding physical page is shipped.

It should be noted that this all only works if pgfpages is loaded after hyperref since hyperref's shipout hook may only be called for physical pages.

% Save and restore pdfpage related information for hyperref.

% Create new counter to save the page counter.
\newcount\pgfpages@state@c@page

% The special per-page label 'thispdfpagelabel' is set/cleared
% globally during hyperref's shipout hook for physical pages.
% Therefore it must be saved temporarily before physical shipout.
\def\pgfpages@state@save@temp{%
\ifHy@pdfpagelabels%
% \HyPL@thisLabel is only defined if pdfpagelabels are activated.
\let\pgfpages@state@thisLabel@temp\HyPL@thisLabel%
\fi%
}

% Save all relevant page states if the first logical page is shipped.
\def\pgfpages@state@save#1{%
% Probably it should be configurable which logical page is
% considered, but the first page seems reasonable for now.
\ifnum#1=\pgf@firstshipout\relax%
% Save the special per-page label 'thispdfpagelabel', which is
% temporarily saved before.
\ifHy@pdfpagelabels%
\ifx\pgfpages@state@thisLabel@temp\relax%
\global\let\pgfpages@state@thisLabel\relax%
\else%
\xdef\pgfpages@state@thisLabel{\pgfpages@state@thisLabel@temp}%
\fi%
\fi%
% Save the page counter and its formatting.
\global\pgfpages@state@c@page=\c@page%
\global\let\pgfpages@state@thepage\thepage%
% Save the page transition and duration.
\global\let\pgfpages@state@pdfpagetransition\@pdfpagetransition%
\global\let\pgfpages@state@pdfpageduration\@pdfpageduration%
\fi%
}

% Restore all relevant page states.
\def\pgfpages@state@restore{%
% Restore the special per-page label 'thispdfpagelabel'.
\ifHy@pdfpagelabels%
% \HyPL@thisLabel is only defined if pdfpagelabels are activated.
\let\HyPL@thisLabel\pgfpages@state@thisLabel%
\fi%
% Restore the page counter and its formatting.
\c@page=\pgfpages@state@c@page%
\let\thepage\pgfpages@state@thepage%
% Restore the page transition and duration.
\let\@pdfpagetransition\pgfpages@state@pdfpagetransition%
\let\@pdfpageduration\pgfpages@state@pdfpageduration%
}

}{
% Do nothing if hyperref is not loaded.
\def\pgfpages@state@save@temp{}
\def\pgfpages@state@save#1{}
\def\pgfpages@state@restore{}
}

% "Patch" macros of pgfpages.

\def\pgfpages@shipoutshipoutbox{%
\begingroup
\let \protect \noexpand
\@resetactivechars
\global\let\@@if@newlist\if@newlist
\global\@newlistfalse
\@parboxrestore%
% Restore page states before physical shipout:
\pgfpages@state@restore%
\pgfpages@originalshipout%
\vbox{\hbox{%
\hskip-1in%
\vbox to \pgfphysicalheight{%
\vss\box\pgfpages@shipoutbox%
\vskip1in%
}}}%
\endgroup%
}

\def\pgfpages@interceptshipout{%
% Temporarily save some page states which are globally set during
% physical shipout:
\pgfpages@state@save@temp%
\ifnum\pgf@shipoutnextto>0\relax
\def\pgf@next{%
\expandafter\global\expandafter\setbox\csname pgfpages@box@\the\pgf@shipoutnextto\endcsname=\box\voidb@x%
\afterassignment\pgfpages@shipouttestnext%
\pgfpagesshipoutlogicalpage{\the\pgf@shipoutnextto}%
}%
\else%
\ifpgf@holdingphysicalpage% shipout physical page now
{\pgfshipoutphysicalpage}%
\fi%
\ifnum\pgf@logicalpages=0\relax
\def\pgf@next{\pgfpages@originalshipout}%
\else%
\def\pgf@next{%
\expandafter\global\expandafter\setbox\csname pgfpages@box@\the\pgf@currentshipout\endcsname=\box\voidb@x%
\afterassignment\pgfpages@shipouttest%
\pgfpagesshipoutlogicalpage{\the\pgf@currentshipout}%
}%
\fi%
\fi%
\pgf@next%
}

\renewcommand\pgfpagesshipoutlogicalpage[1]{%
\global\pgfphysicalpageemptyfalse%
% Save page states before logical shipout:
\pgfpages@state@save{#1}%
\expandafter\global\expandafter\setbox\csname pgfpages@box@#1\endcsname=}

-
On my system (also with TeXLive 2012) I get the frame numbers as page numbers in the viewer: 1,2,3,3,3,3. Since I get the same numbers without \usepackage{pgfpages} and \setbeameroption, I would consider this the expected behaviour. Did you want to achieve something else? – Bastian Sauert Jun 9 '13 at 19:27
My apologies, this question was from so long ago that I forgot what it was asking. You did indeed explain the cause of the problem and provide a good solution. Thank you! – andrew Jun 9 '13 at 19:41
Has anybody else gotten this to work? On my system, this causes pdflatex to just churn (i.e., it occupies CPU time but does not return). – Benjamin Mako Hill May 27 '14 at 21:46