# Why tikzmark doesn't work with beamer class?

Consider the following MCE that makes use of:

• tikzmark library and its listings library that let us add marks to lstlisting environments,
• the high level \balloon macro (provided by the tikzmark's author in https://tex.stackexchange.com/a/86457/18401) that puts a fancy node behind certain lines of the code (it is here a bit modified in order to avoid overlapping of the line preceding the first one wanted, see Jellby's comment on Mar 9 '14 at 18:26 in https://tex.stackexchange.com/a/79787/18401).

The point is, this code works nicely with e.g. the article class but not with the beamer one: with the latter, the node isn't displayed.

% \documentclass{beamer}
\documentclass{article}\usepackage{beamerarticle}
%
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{tikzmark,fit,calc}
\usetikzmarklibrary{listings}
\lstset{basicstyle=\ttfamily}
\tikzset{
balloon/.style={
draw,
fill=blue!20,
opacity=0.4,
inner sep=4pt,
rounded corners=2pt
},
}
%
\newcommand{\balloon}[4]{%
\pgfmathtruncatemacro\firstline{%
#3-1%
}%
\iftikzmark{line-#2-\firstline-start}{%
\iftikzmark{line-#2-#3-first}{%
\xdef\blines{($({pic cs:line-#2-\firstline-start} -| {pic cs:line-#2-#3-first})!.5!({pic cs:line-#2-#3-first})$)}%
}{%
\iftikzmark{line-#2-#3-start}{%
\xdef\blines{({pic cs:line-#2-\firstline-start} -| {pic
cs:line-#2-#3-start})}%
}{%
\xdef\blines{(pic cs:line-#2-\firstline-start)}%
}%
}%
}{%
\xdef\blines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first}{%
\xdef\blines{\blines (pic cs:line-#2-\k-first) }%
}{} \iftikzmark{line-#2-\k-end}{%
\xdef\blines{\blines (pic cs:line-#2-\k-end) }%
}{}%
}%
\ifx\blines\empty
\else
\edef\temp{\noexpand\tikz[remember picture,overlay]
\noexpand\node[fit={\blines},balloon] (#1) {};}%
\temp
\fi
}
%
\begin{document}
\begin{frame}[fragile]
\balloon{comment}{code}{3}{4}
\begin{lstlisting}[name=code]
Foo Bar Baz
Foo Baz Bar
Bar Foo Baz
Bar Baz Foo
Baz Foo Bar
Baz Bar Foo
\end{lstlisting}
\end{frame}
\end{document}


# Results

## With beamer

• see for example tex.stackexchange.com/questions/240542/… – user36296 Jan 31 '17 at 13:10
• @samcarter Well, I don't see what can help me concerning beamer in this question and its answer and comments. Could you elaborate? Thanks! – Denis Bitouzé Jan 31 '17 at 13:23
• If you would use \marktopleft and \markbottomright as escaped code sequences inside your listing? – user36296 Jan 31 '17 at 13:26
• @samcarter Indeed, that works. But the nice feature of tikzmark library (and its listings library) and the \balloon macro is that they don't need the listing content to be changed. Therefore they apply to a listing input thanks to \lstinputlisting. Currently, I don't see why \marktopleft and \markbottomright from this question work nicely and not this \balloon macro. – Denis Bitouzé Jan 31 '17 at 13:47

beamer redefines \pgfmark and adds a number for the slide to the internal name to make if overlay aware. If you look at the aux you can see that you get names like line-code-6-start-1 instead of line-code-6-start. This means that all your \iftikzmark fails.

\documentclass{beamer}
%\documentclass{article}\usepackage{beamerarticle}
%
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{tikzmark,fit,calc}
\usetikzmarklibrary{listings}
\lstset{basicstyle=\ttfamily}
\tikzset{
balloon/.style={
draw,
fill=blue!20,
opacity=0.4,
inner sep=4pt,
rounded corners=2pt
},
}

\makeatletter

%
\newcommand{\balloon}[4]{%
\pgfmathtruncatemacro\firstline{%
#3-1%
}%
\iftikzmark{line-#2-\firstline-start-\the \beamer@slideinframe}{%
\iftikzmark{line-#2-#3-first-\the \beamer@slideinframe}{%
\xdef\blines{($({pic cs:line-#2-\firstline-start} -| {pic cs:line-#2-#3-first})!.5!({pic cs:line-#2-#3-first})$)}%
}{%
\iftikzmark{line-#2-#3-start-\the \beamer@slideinframe}{%
\xdef\blines{({pic cs:line-#2-\firstline-start} -| {pic
cs:line-#2-#3-start})}%
}{%
\xdef\blines{(pic cs:line-#2-\firstline-start)}%
}%
}%
}{%
\xdef\blines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first-\the \beamer@slideinframe}{%
\xdef\blines{\blines (pic cs:line-#2-\k-first) }%
}{} \iftikzmark{line-#2-\k-end-\the \beamer@slideinframe}{%
\xdef\blines{\blines (pic cs:line-#2-\k-end) }%
}{}%
}%
\ifx\blines\empty
\else
\edef\temp{\noexpand\tikz[remember picture,overlay]
\noexpand\node[fit={\blines},balloon] (#1) {};}%
\temp
\fi
}
%
\begin{document}

\begin{frame}[fragile]
\balloon{comment}{code}{3}{4}

\begin{lstlisting}[name=code]
Foo Bar Baz
Foo Baz Bar
Bar Foo Baz
Bar Baz Foo
Baz Foo Bar
Baz Bar Foo
\end{lstlisting}
\end{frame}
\end{document}


An alternative to the redefinition of \ballon is a redefinition of \iftikzmark:

\makeatletter
\renewcommand\iftikzmark[3]{%
\@ifundefined{save@pt@#1-\the\beamer@slideinframe}{%
#3%
}{%
#2%
}%
}%

• Very nice! :) However, is it possible to make the \balloon macro overlay aware or, at least , to make it work if given as an argument of e.g. \only<...> command? – Denis Bitouzé Jan 31 '17 at 14:10
• About making the \balloon macro overlay aware, see for instance tex.stackexchange.com/q/351434/18401. – Denis Bitouzé Feb 2 '17 at 8:27

It looks like this problem has been fixed upstream by https://github.com/loopspace/tikzmark/commit/1427ccaa0be7932d964d3f51b26b5a4d3444e1af or https://github.com/loopspace/tikzmark/commit/00141c09c0b53c14459c206dc23ea6ea90f96b0b

So if you use the work-around presented above on a recent TeXlive distribution (I have tried on Ubuntu 19.04 & 19.10 and Debian/unstable) it does not work... You need now to go back to the first example of this page.

• Hi, as it's possible that your "answer" here will get deleted, can I encourage you to let me know via github if there's still a problem with tikzmark. The latest version got to ctan only very recently so will take time to get to debian, I expect. I try not to introduce new bugs each time but I'm not always successful! – Loop Space Oct 11 at 17:24
• With an up to date TeX Live 2019 (vanilla install on a Linux box), the Ulrike's workaround still works like a charm. BTW, your answer would probably better have been a comment. – Denis Bitouzé Oct 11 at 20:12