1

I'd like to define a frame option in Beamer to "invert" the colors of background, foreground, and structure, and I can do so by defining

\documentclass{beamer}

\BeforeBeginEnvironment{frame}{%
  \setbeamercolor{normal text}{fg=black, bg=white}%
  \setbeamercolor{structure}{fg=blue}%
  \usebeamercolor[fg]{normal text}%
}

\makeatletter
\define@key{beamerframe}{bg}[true]{%
  \setbeamercolor{normal text}{fg=white, bg=black}%
  \setbeamercolor{structure}{fg=red}%
  \usebeamercolor[fg]{normal text}%
}
\makeatother

\begin{document}
  \begin{frame}
    \frametitle{Normal}
  \end{frame}

  \begin{frame}[bg]
    \frametitle{Inverted}
    A statement
  \end{frame}
\end{document}

which results in success?

However, assigning the frame a label

\begin{frame}[bg, label=test]
  \frametitle{Inverted}
  A statement
\end{frame}

results in the error

Package keyval Error: label undefined \end{frame}

Now this is already a problem, but we could say only a minor problem, since it can be circumvented by placing the label first.

Things really start to spiral out of my control when I'd like to reuse the frame

\begin{document}
  \begin{frame}<1>[label=test, bg]
    \frametitle{Inverted}
    \only<1>{A statement}
    \only<2>{Another statement}
    \only<3>{Third statement}
  \end{frame}

  \againframe<2>{test}

  \begin{frame}
    \frametitle{Normal}
  \end{frame}

  \againframe<3>{test}
\end{document}

failure Somehow the frame option affects all contiguous frames, but not if there's a "normal" frame in-between.

The behaviour I was expecting to see, is that the inversion would not affect the repeated frames, but instead the frame option would need to be passed again. However, doing that

\againframe<3>[bg]{test}

results in the error

Package keyval Error: relabel undefined 

If changing only the frame background following the example of https://tex.stackexchange.com/a/395429/199342, the label order issue disappears, as does the issue of not being able to pass the option to \againframe. Nevertheless, the frame option still affects contiguous frames even without passing the option, but passing it does not result in any errors either.

\documentclass{beamer}

\defbeamertemplate*{background canvas}{mydefault}{%
  \ifbeamercolorempty[bg]{background canvas}{}{\color{bg}\vrule width\paperwidth height\paperheight}%
}

\defbeamertemplate*{background canvas}{bg}{%
  \color{black}\vrule width\paperwidth height\paperheight%
}

\BeforeBeginEnvironment{frame}{%
  \setbeamertemplate{background canvas}[mydefault]%
}
\makeatletter
\define@key{beamerframe}{bg}[true]{%
  \setbeamertemplate{background canvas}[bg]%
}
\makeatother

\begin{document}
  \begin{frame}<1>[bg, label=test]
    \frametitle{Inverted}
    \only<1>{First point}
    \only<2>{Second point}
    \only<3>{Third point}
  \end{frame}

  \againframe<2>{test}

  \begin{frame}
    \frametitle{Normal}
  \end{frame}

  \againframe<3>[bg]{test}
\end{document}

background

But I'd really like the frame option to change the font colors as well. Is there some way to achieve the functionality I'm looking for?

1 Answer 1

0

The issue is the same as in noframenumbering in Metropolis' standout frames you're nesting \setkeys calls which aren't nestable. As a result the label key isn't parsed as part of the optional argument of frame but as part of the set used for \setbeamercolor.

Incidentally that question also contains a fix for your color-leakage problem. You try to revert the colours using \BeforeBeginEnvironment, but the frame environment isn't used by \againframe so your resetting code isn't executed. The fix would be to revert the colours at the end of the frame bg is applied to (by scoping it using \begingroup...\endgroup with a conditional to keep track of it).

The following patches \setkeys to be nestable and implements the fix for your colour settings.

\documentclass{beamer}

\makeatletter
% patch \setkeys to be nestable:
\NewCommandCopy\my@setkeys@orig\setkeys
\def\setkeys{\expandafter\my@setkeys@aux\expandafter{\KV@prefix}}
\long\def\my@setkeys@aux#1#2#3{\my@setkeys@orig{#2}{#3}\def\KV@prefix{#1}}


\newif\ifbgframe
\define@key{beamerframe}{bg}[true]{%
  \bgframetrue
  \begingroup
  \setbeamercolor{normal text}{fg=white, bg=black}%
  \setbeamercolor{structure}{fg=red}%
  \usebeamercolor[fg]{normal text}%
}
\pretocmd{\beamer@reseteecodes}{%
  \ifbgframe
    \endgroup
    \bgframefalse
  \fi
}{}{}
\makeatother

\begin{document}
  \begin{frame}<1>[bg, label=test]
    \frametitle{Inverted}
    \only<1>{A statement}
    \only<2>{Another statement}
    \only<3>{Third statement}
  \end{frame}

  \againframe<2>{test}

  \begin{frame}
    \frametitle{Normal}
  \end{frame}

  \againframe<3>{test}
\end{document}

\begin{document}
  \begin{frame}
    \frametitle{Normal}
  \end{frame}

  \begin{frame}[bg]
    \frametitle{Inverted}
    A statement
  \end{frame}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.