[Tex/LaTex] Beamer: make slide transitions dependent only on slide content when notes hidden

beamernotestransition

I have developed a presentation in which I used notes a lot, and often have delays between points on the slides because a single point may have multiple notes associated with it, so it takes multiple clicks to get to the next point because each click is bringing up another note on the notes page.

However, when compiling without notes, I would like it to automatically transition only based on the frame content. This is extra tricky because I've hard coded a lot of delays in my slide content. I've included a MWE that shows what I mean.

If you compile it with and without notes (see the two options at the top), you will see what I mean. With notes one, every time you click down, something changes, either on the notes slide or the slide itself. However, with notes off, it often takes multiple clicks to progress because it's factoring in either a) multiple notes or b) a delay introduced in the slide itself with the uncover command.

Is there a compile option that will make Beamer automatically and intelligently ignore any notes delays and in-slide delays that do not result in a slide transition such that, when compiling without notes, you will always have a slide transition with a click or page down?

I realize it was a mistake to have hard coded delays in the slides themselves, but it seems the notes should not have this effect, and because of the length of my presentation, I'm hoping this can be done automatically with a little Beamer hacking or patching.

Thanks.

MWE:

% 1. NO NOTES
%\documentclass[]{beamer}

%% 2. DUAL-DISPLAY NOTES:
\documentclass[hyperref={bookmarks=true}]{beamer}
\usepackage{pgfpages}
\setbeameroption{show notes on second screen=left}

\usepackage[english]{babel}
\mode<presentation>{
  \usetheme{Warsaw}
    \setbeamercovered{transparent}}

\begin{document}

\begin{frame}{Introduction}{}

\begin{itemize}
    \uncover<1->{\item Here is my first point}
  \uncover<2->{\item Here is my second point}
    \uncover<4->{\item With notes on, I would expect it to take two clicks to get here from the last point, since there are two notes. But with them off, I would expect it to take one click.}
    \uncover<5->{\item This is my third point. I have four notes about this point, so with notes on, it should take three more clicks to get to the next slide. With them off, however, it should take one. }
\end{itemize}

\note[item]<1->{Here is a note about my first point}
\note[item]<2->{Here is a note about my second point}
\note[item]<3->{Here is \textbf{another} note about my second point}
\note[item]<4->{Here is a note about my third point}
\note[item]<5->{Here is the second of several more notes about my third point}
\note[item]<6->{Another one}
\note[item]<7->{And another}
\end{frame}

\begin{frame}{Another slide}{}
\begin{itemize}
    \uncover<1->{\item Not much to say here}
\end{itemize}
\end{frame}

\end{document}

Best Answer

Here's something that works with the example you posted, but might not work with more sophisticated overlay specifications. There are two parts to the method. The first is a little addition to the overlay code which tries to establish whether the current frame was explicitly mentioned, for example the 3 in \uncover<3->, or not, for example frame 4 in \uncover<4->. If explicitly mentioned, it sets a flag. The second part to the method is a little addition to pgfpages, imaginatively called pgfmorepages (CTAN and github), which - amongst other things - introduces the possibility of skipping a page when shipping out pages. So this looks for the flag set by the first part of the code and if it doesn't find it, it ignores the particular page.

There is a snag. You can't use the transparent option. That is because this does some look-ahead stuff and asks "Is this going to appear in a frame or two's time?" So it runs the overlay specifications with other frame numbers than the current one and that messes up the testing.

The other annoying bit is that each frame has to start with the command \mentionedsetup. This could be automated by adding it to one of the templates.

Here's the code with some sample frames.

%\url{http://tex.stackexchange.com/q/56990/86}
% 1. NO NOTES
\documentclass[]{beamer}

%% 2. DUAL-DISPLAY NOTES:
%\documentclass[hyperref={bookmarks=true}]{beamer}
\usepackage{pgfmorepages}
%\setbeameroption{show notes on second screen=left}

\makeatletter

\newif\if@mentioned
\@mentionedtrue

\pgfpagesdeclarelayout{1 on 1 with possible skip}
{
  \def\pgfpageoptionborder{0pt}
}
{
  \pgfpagesphysicalpageoptions
  {%
    logical pages=1,%
    physical pages=1,%
    first logical shipout=1,%
    last logical shipout=1,%
    current logical shipout=1,%
  }
  \pgfpagesphysicalpage{1}{
    skip code={%
      \if@mentioned
      \pgfpagesshiptrue
      \else
      \pgfpagesshipfalse
      \fi
    }
  }
  \pgfpageslogicalpageoptions{1}
  {%
    center=\pgfpoint{.5\pgfphysicalwidth}{.5\pgfphysicalheight},%
  }%
}

\pgfpagesuselayout{1 on 1 with possible skip}

\def\slidereferenced{%
  \ifbeamer@inframe
  \global\@mentionedtrue
  \fi
}

\def\mentionedsetup{%
  \ifnum\beamer@slideinframe=1
  \global\@mentionedtrue
  \else
  \global\@mentionedfalse
  \fi
}

\expandafter\let\csname
beamerx@\string\beamer@inframenote\endcsname\relax
\renewcommand<>{\beamer@inframenote}[2][]{}

\def\beamer@decodeuntil-#1,{%
  \ifnum1<\beamer@minimum\global\beamer@minimum=1\fi%
  \ifnum#1>\beamer@slideinframe\global\beamer@anotherslidetrue\beamer@localanotherslidetrue\fi%
  \ifnum\beamer@slideinframe>#1\else\gdef\beamer@doifnotinframe{\beamer@doifinframe}\fi%
  \ifnum\beamer@slideinframe=#1\relax\slidereferenced\fi%
  \beamer@@decode}
\def\beamer@decodeto#1,{%
  \ifnum#1<\beamer@minimum\global\beamer@minimum=#1\fi%
  \ifnum#1>\beamer@slideinframe\global\beamer@anotherslidetrue\beamer@localanotherslidetrue\fi%
  \ifnum#1>\beamer@slideinframe\else\gdef\beamer@doifnotinframe{\beamer@doifinframe}\fi%
  \ifnum\beamer@slideinframe=#1\relax\slidereferenced\fi%
  \beamer@@decode}
\def\beamer@decodebetween#1#2,{%
  \ifnum#1<\beamer@minimum\global\beamer@minimum=#1\fi%
  \ifnum#1>\beamer@slideinframe\global\beamer@anotherslidetrue\beamer@localanotherslidetrue\fi%
  \ifnum#2>\beamer@slideinframe\global\beamer@anotherslidetrue\beamer@localanotherslidetrue\fi%
  \ifnum#1>\beamer@slideinframe\else\ifnum#2<\beamer@slideinframe\else\gdef\beamer@doifnotinframe{\beamer@doifinframe}\fi\fi%
  \ifnum\beamer@slideinframe=#1\relax\slidereferenced\fi%
  \ifnum\beamer@slideinframe=#2\relax\slidereferenced\fi%
  \beamer@@decode}
\def\beamer@decodeone#1,{%
  \ifnum#1<\beamer@minimum\global\beamer@minimum=#1\fi%
  \ifnum#1>\beamer@slideinframe\global\beamer@anotherslidetrue\beamer@localanotherslidetrue\fi%
  \ifnum#1=\beamer@slideinframe\gdef\beamer@doifnotinframe{\beamer@doifinframe}\fi%
  \ifnum\beamer@slideinframe=#1\relax\slidereferenced\fi%
  \beamer@@decode}

\makeatother

\usepackage[english]{babel}
\mode<presentation>{
  \usetheme{Warsaw}
%    \setbeamercovered{transparent}
}

\begin{document}

\begin{frame}{Testing}
\mentionedsetup
\uncover<1->{hello}
\uncover<3->{world}
\uncover<5->{greetings}
\uncover<7->{earthlings}

\end{frame}

\begin{frame}{Introduction}{}
\mentionedsetup
\begin{itemize}
\item hello world
    \uncover<1->{\item Here is my first point}
  \uncover<2->{\item Here is my second point}
    \uncover<4->{\item With notes on, I would expect it to take two
clicks to get here from the last point, since there are two notes. But
with them off, I would expect it to take one click.}
    \uncover<5->{\item This is my third point. I have four notes about
this point, so with notes on, it should take three more clicks to get
to the next slide. With them off, however, it should take one. }
\end{itemize}

\note[item]<1->{Here is a note about my first point}
\note[item]<2->{Here is a note about my second point}
\note[item]<3->{Here is \textbf{another} note about my second point}
\note[item]<4->{Here is a note about my third point}
\note[item]<5->{Here is the second of several more notes about my
third point}
\note[item]<6->{Another one}
\note[item]<7->{And another}
\end{frame}

\begin{frame}{Another slide}{}
\begin{itemize}
    \uncover<1->{\item Not much to say here}
\end{itemize}
\end{frame}

\end{document}

Oh, and we have to redefine the \note command. Even when the notes aren't shown, the command is processed. So we have to redefine it to be a NO-OP to ensure that the resulting overlays aren't read.

Here's the first few frames of the above, showing that frames 2,4,6 get skipped.

beamer notes with frames removed