Gtk4-tutorial/docs/sec18.html
Toshio Sekiya 7b14d03a24 Change the width of HTML contents.
Update the distribution package information.
2023-12-10 16:39:32 +08:00

533 lines
49 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<title>GTK 4 tutorial</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre{overflow: visible;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::after
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
td {padding: 2px 6px; border: 1px solid;}
img {display: block; margin-left: auto; margin-right: auto;}
figcaption {text-align: center;}
</style>
</head>
<body style="padding-top: 70px;">
<div class="container">
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<span class="navbar-brand">Gtk4 tutorial</span>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec17.html">Prev: section17</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec19.html">Next: section19</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="row justify-content-center">
<div class="col-xl-10 col-xxl-9">
<h1 id="stateful-action">Stateful action</h1>
<p>Some actions have states. The typical values of states are boolean or
string. However, other types of states are possible if you want.</p>
<p>Actions which have states are called stateful.</p>
<h2 id="stateful-action-without-a-parameter">Stateful action without a
parameter</h2>
<p>Some menus are called toggle menu. For example, fullscreen menu has a
state which has two values fullscreen and non-fullscreen. The value of
the state is changed every time the menu is clicked. An action
corresponds to the fullscreen menu also have a state. Its value is TRUE
or FALSE and it is called boolean value. TRUE corresponds to fullscreen
and FALSE to non-fullscreen.</p>
<p>The following is an example code to implement a fullscreen menu
except the signal handler. The signal handler will be shown later.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>GSimpleAction <span class="op">*</span>act_fullscreen <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">&quot;fullscreen&quot;</span><span class="op">,</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> NULL<span class="op">,</span> g_variant_new_boolean <span class="op">(</span>FALSE<span class="op">));</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_fullscreen<span class="op">,</span> <span class="st">&quot;change-state&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>fullscreen_changed<span class="op">),</span> win<span class="op">);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_fullscreen<span class="op">));</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_fullscreen <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Full Screen&quot;</span><span class="op">,</span> <span class="st">&quot;win.fullscreen&quot;</span><span class="op">);</span></span></code></pre></div>
<ul>
<li><code>act_fullscreen</code> is a GSimpleAction instance. It is
created with <code>g_simple_action_new_stateful</code>. The function has
three arguments. The first argument “fullscreen” is the name of the
action. The second argument is a parameter type. <code>NULL</code> means
the action doesnt have a parameter. The third argument is the initial
state of the action. It is a GVariant value. GVariant will be explained
in the next subsection. The function
<code>g_variant_new_boolean (FALSE)</code> returns a boolean type
GVariant value which is <code>FALSE</code>. If there are two or more top
level windows, each window has its own <code>act_fullscreen</code>
action. So, the number of the actions is the same as the number of the
windows.</li>
<li>The action <code>act_fullscreen</code> has “change-state” signal.
The signal is connected to a handler <code>fullscreen_changed</code>. If
the fullscreen menu is clicked, then the corresponding action
<code>act_fullscreen</code> is activated. But no handler is connected to
the “activate” signal. Then, the default behavior for boolean-stated
actions with a NULL parameter type like <code>act_fullscreen</code> is
to toggle them via the “change-state” signal.</li>
<li>The action is added to the GtkWindow <code>win</code>. Therefore,
the scope of the action is “win”.</li>
<li><code>menu_item_fullscreen</code> is a GMenuItem instance. There are
two arguments. The first argument “Full Screen” is the label of
<code>menu_item_fullscreen</code>. The second argument is an action. The
action “win.fullscreen” has a prefix “win” and an action name
“fullscreen”. The prefix says that the action belongs to the
window.</li>
</ul>
<div class="sourceCode" id="cb2"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>fullscreen_changed<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>value<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3"></a> <span class="cf">if</span> <span class="op">(</span>g_variant_get_boolean <span class="op">(</span>value<span class="op">))</span></span>
<span id="cb2-4"><a href="#cb2-4"></a> gtk_window_maximize <span class="op">(</span>win<span class="op">);</span></span>
<span id="cb2-5"><a href="#cb2-5"></a> <span class="cf">else</span></span>
<span id="cb2-6"><a href="#cb2-6"></a> gtk_window_unmaximize <span class="op">(</span>win<span class="op">);</span></span>
<span id="cb2-7"><a href="#cb2-7"></a> g_simple_action_set_state <span class="op">(</span>action<span class="op">,</span> value<span class="op">);</span></span>
<span id="cb2-8"><a href="#cb2-8"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>The handler <code>fullscreen_changed</code> has three parameters.
The first parameter is the action which emits the “change-state” signal.
The second parameter is the value of the new state of the action. The
third parameter is a user data which is set in
<code>g_signal_connect</code>.</li>
<li>If the value is boolean type and <code>TRUE</code>, then it
maximizes the window. Otherwise it un-maximizes.</li>
<li>Sets the state of the action with <code>value</code>. Note: At this
stage, that means the stage before
<code>g_simple_action_set_state</code> is called, the state of the
action still has the original value. So, you need to set the state with
the new value by <code>g_simple_action_set_state</code>.</li>
</ul>
<p>You can use “activate” signal instead of “change-state” signal, or
both signals. But the way above is the simplest and the best.</p>
<h3 id="gvariant">GVariant</h3>
<p>GVariant is a fundamental type. It isnt a child of GObject. GVariant
can contain boolean, string or other type values. For example, the
following program assigns TRUE to <code>value</code> whose type is
GVariant.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>GVariant <span class="op">*</span>value <span class="op">=</span> g_variant_new_boolean <span class="op">(</span>TRUE<span class="op">);</span></span></code></pre></div>
<p>Another example is:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>GVariant <span class="op">*</span>value2 <span class="op">=</span> g_variant_new_string <span class="op">(</span><span class="st">&quot;Hello&quot;</span><span class="op">);</span></span></code></pre></div>
<p><code>value2</code> is a GVariant and it has a string type value
“Hello”. GVariant can contain other types like int16, int32, int64,
double and so on.</p>
<p>If you want to get the original value, use g_variant_get series
functions. For example, you can get the boolean value with
g_variant_get_boolean.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>gboolean <span class="dt">bool</span> <span class="op">=</span> g_variant_get_boolean <span class="op">(</span>value<span class="op">);</span></span></code></pre></div>
<p>Since <code>value</code> has been created as a boolean type GVariant
with <code>TRUE</code> value, <code>bool</code> equals
<code>TRUE</code>. In the same way, you can get a string from
<code>value2</code></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>str <span class="op">=</span> g_variant_get_string <span class="op">(</span>value2<span class="op">,</span> NULL<span class="op">);</span></span></code></pre></div>
<p>The second parameter is a pointer to gsize type variable (gsize is
defined as unsigned long). If it isnt NULL, then the pointed value is
used as the length by the function. If it is NULL, nothing happens. The
returned string <code>str</code> is owned by the instance and cant be
changed or freed by the caller.</p>
<h2 id="stateful-action-with-a-parameter">Stateful action with a
parameter</h2>
<p>Another example of stateful actions is an action corresponds to color
select menus. For example, there are three menus and each menu has red,
green or blue color respectively. They determine the background color of
a GtkLabel widget. One action is connected to the three menus. The
action has a state whose value is “red”, “green” or “blue”. The values
are string. Those colors are given to the signal handler as a
parameter.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new<span class="op">(</span><span class="st">&quot;s&quot;</span><span class="op">);</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>GSimpleAction <span class="op">*</span>act_color</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">&quot;color&quot;</span><span class="op">,</span> vtype<span class="op">,</span> g_variant_new_string <span class="op">(</span><span class="st">&quot;red&quot;</span><span class="op">));</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_red <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Red&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::red&quot;</span><span class="op">);</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_green <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Green&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::green&quot;</span><span class="op">);</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>GMenuItem <span class="op">*</span>menu_item_blue <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Blue&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::blue&quot;</span><span class="op">);</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_color<span class="op">,</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>color_activated<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span> <span class="op">...</span></span></code></pre></div>
<ul>
<li>GVariantType is a C structure and it keeps a type of GVariant. It is
created with the function <code>g_variant_type_new</code>. The argument
of the function is a GVariant type string. So,
<code>g_variant_type_new("s")</code> returns a GVariantType structure
contains a string type. The returned value, GVariantType structure, is
owned by the caller. So, you need to free it when it becomes
useless.</li>
<li>The variable <code>act_color</code> points a GSimpleAction instance.
It is created with <code>g_simple_action_new_stateful</code>. The
function has three arguments. The first argument “color” is the name of
the action. The second argument is a parameter type which is
GVariantType. <code>g_variant_type_new("s")</code> creates GVariantType
which is a string type (<code>G_VARIANT_TYPE_STRING</code>). The third
argument is the initial state of the action. It is a GVariant. The
function <code>g_variant_new_string ("red")</code> returns a GVariant
value which has the string value “red”. GVariant has a reference count
and <code>g_variant_new_...</code> series functions returns a GVariant
value with a floating reference. That means the caller doesnt own the
value at this point. And <code>g_simple_action_new_stateful</code>
function consumes the floating reference so you dont need to care about
releasing the GVariant instance.</li>
<li>The GVariantType structure <code>vtype</code> is useless after
<code>g_simple_action_new_stateful</code>. It is released with the
function <code>g_variant_type_free</code>.</li>
<li>The varable <code>menu_item_red</code> points a GMenuItem instance.
The function <code>g_menu_item_new</code> has two arguments. The first
argument “Red” is the label of <code>menu_item_red</code>. The second
argument is a detailed action. Its prefix is “app”, action name is
“color” and target is “red”. Target is sent to the action as a
parameter. The same goes for <code>menu_item_green</code> and
<code>menu_item_blue</code>.</li>
<li>The function <code>g_signal_connect</code> connects the activate
signal on the action <code>act_color</code> and the handler
<code>color_activated</code>. If one of the three menus is clicked, then
the action <code>act_color</code> is activated with the target
(parameter) which is given by the menu.</li>
</ul>
<p>The following is the “activate” signal handler.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>color_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">char</span> <span class="op">*</span>color <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">&quot;label.lb {background-color: %s;}&quot;</span><span class="op">,</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> g_variant_get_string <span class="op">(</span>parameter<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> color<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> g_free <span class="op">(</span>color<span class="op">);</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> g_action_change_state <span class="op">(</span>G_ACTION <span class="op">(</span>action<span class="op">),</span> parameter<span class="op">);</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>The handler originally has three parameters. The third parameter is
a user data set in the <code>g_signal_connect</code> function. But it is
left out because the fourth argument of the
<code>g_signal_connect</code> has been NULL. The first parameter is the
action which emits the “activate” signal. The second parameter is the
parameter, or target, given to the action. It is a color specified by
the menu.</li>
<li>The variable <code>color</code> is a CSS string created by
<code>g_strdup_printf</code>. The arguments of
<code>g_strdup_printf</code> are the same as printf C standard function.
The function <code>g_variant_get_string</code> gets the string contained
in <code>parameter</code>. The string is owned by the instance and you
mustnt change or free it. The string <code>label.lb</code> is a
selector. It consists of <code>label</code>, a node name of GtkLabel,
and <code>lb</code> which is a class name. It selects GtkLabel which has
<code>lb</code> class. For example, menus have GtkLabel to display their
labels, but they dont have <code>lb</code> class. So, the CSS doesnt
change their background color. The string
<code>{background-color %s}</code> makes the background color
<code>%s</code> to which the color from <code>parameter</code> is
assigned.</li>
<li>Frees the string <code>color</code>.</li>
<li>Changes the state with <code>g_action_change_state</code>.</li>
</ul>
<p>Note: If you havent set an “activate” signal handler, the signal is
forwarded to “change-state” signal. So, you can use “change-state”
signal instead of “activate” signal. See
<code>src/menu/menu2_change_state.c</code>.</p>
<h3 id="gvarianttype">GVariantType</h3>
<p>GVariantType gives a type of GVariant. GVariantType is created with a
type string.</p>
<ul>
<li>“b” means boolean type.</li>
<li>“s” means string type.</li>
</ul>
<p>The following program is a simple example. It finally outputs the
string “s”.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1"></a><span class="pp">#include </span><span class="im">&lt;glib.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a></span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="dt">int</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5"></a> GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new <span class="op">(</span><span class="st">&quot;s&quot;</span><span class="op">);</span></span>
<span id="cb9-6"><a href="#cb9-6"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>type_string <span class="op">=</span> g_variant_type_peek_string <span class="op">(</span>vtype<span class="op">);</span></span>
<span id="cb9-7"><a href="#cb9-7"></a> g_print <span class="op">(</span><span class="st">&quot;%s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span>type_string<span class="op">);</span></span>
<span id="cb9-8"><a href="#cb9-8"></a> g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
<span id="cb9-9"><a href="#cb9-9"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>The function <code>g_variant_type_new</code> creates a GVariantType
structure. The argument “s” is a type string. It means string. The
returned structure is owned by the caller. When it becomes useless, you
need to free it with the function <code>g_variant_type_free</code>.</li>
<li>The function <code>g_variant_type_peek_string</code> takes a peek at
<code>vtype</code>. It is the string “s” given to <code>vtype</code>
when it was created. The string is owned by the instance and the caller
cant change or free it.</li>
<li>Prints the string to the terminal. You cant free <code>vtype</code>
before <code>g_print</code> because the string <code>type_string</code>
is owned by <code>vtype</code>.</li>
<li>Frees <code>vtype</code>.</li>
</ul>
<h2 id="example">Example</h2>
<p>The following code includes stateful actions above. This program has
menus like this:</p>
<figure>
<img src="image/menu2.png" alt="menu2" />
<figcaption aria-hidden="true">menu2</figcaption>
</figure>
<ul>
<li>Fullscreen menu toggles the size of the window between maximum and
non-maximum. If the window is maximum size, which is called full screen,
then a check mark is put before “fullscreen” label.</li>
<li>Red, green and blue menu determines the back ground color of the
label in the window. The menus have radio buttons on the left of the
menus. And the radio button of the selected menu turns on.</li>
<li>Quit menu quits the application.</li>
</ul>
<p>The code is as follows.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2"></a></span>
<span id="cb10-3"><a href="#cb10-3"></a><span class="co">/* The provider below provides application wide CSS data. */</span></span>
<span id="cb10-4"><a href="#cb10-4"></a>GtkCssProvider <span class="op">*</span>provider<span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5"></a></span>
<span id="cb10-6"><a href="#cb10-6"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb10-7"><a href="#cb10-7"></a>fullscreen_changed<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>value<span class="op">,</span> GtkWindow <span class="op">*</span>win<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8"></a> <span class="cf">if</span> <span class="op">(</span>g_variant_get_boolean <span class="op">(</span>value<span class="op">))</span></span>
<span id="cb10-9"><a href="#cb10-9"></a> gtk_window_maximize <span class="op">(</span>win<span class="op">);</span></span>
<span id="cb10-10"><a href="#cb10-10"></a> <span class="cf">else</span></span>
<span id="cb10-11"><a href="#cb10-11"></a> gtk_window_unmaximize <span class="op">(</span>win<span class="op">);</span></span>
<span id="cb10-12"><a href="#cb10-12"></a> g_simple_action_set_state <span class="op">(</span>action<span class="op">,</span> value<span class="op">);</span></span>
<span id="cb10-13"><a href="#cb10-13"></a><span class="op">}</span></span>
<span id="cb10-14"><a href="#cb10-14"></a></span>
<span id="cb10-15"><a href="#cb10-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb10-16"><a href="#cb10-16"></a>color_activated<span class="op">(</span>GSimpleAction <span class="op">*</span>action<span class="op">,</span> GVariant <span class="op">*</span>parameter<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-17"><a href="#cb10-17"></a> <span class="dt">char</span> <span class="op">*</span>color <span class="op">=</span> g_strdup_printf <span class="op">(</span><span class="st">&quot;label.lb {background-color: %s;}&quot;</span><span class="op">,</span> g_variant_get_string <span class="op">(</span>parameter<span class="op">,</span> NULL<span class="op">));</span></span>
<span id="cb10-18"><a href="#cb10-18"></a> <span class="co">/* Change the CSS data in the provider. */</span></span>
<span id="cb10-19"><a href="#cb10-19"></a> <span class="co">/* Previous data is thrown away. */</span></span>
<span id="cb10-20"><a href="#cb10-20"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> color<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb10-21"><a href="#cb10-21"></a> g_free <span class="op">(</span>color<span class="op">);</span></span>
<span id="cb10-22"><a href="#cb10-22"></a> g_action_change_state <span class="op">(</span>G_ACTION <span class="op">(</span>action<span class="op">),</span> parameter<span class="op">);</span></span>
<span id="cb10-23"><a href="#cb10-23"></a><span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24"></a></span>
<span id="cb10-25"><a href="#cb10-25"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb10-26"><a href="#cb10-26"></a>app_shutdown <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">,</span> GtkCssProvider <span class="op">*</span>provider<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-27"><a href="#cb10-27"></a> gtk_style_context_remove_provider_for_display <span class="op">(</span>gdk_display_get_default<span class="op">(),</span> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">));</span></span>
<span id="cb10-28"><a href="#cb10-28"></a><span class="op">}</span></span>
<span id="cb10-29"><a href="#cb10-29"></a></span>
<span id="cb10-30"><a href="#cb10-30"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb10-31"><a href="#cb10-31"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-32"><a href="#cb10-32"></a> GtkWindow <span class="op">*</span>win <span class="op">=</span> GTK_WINDOW <span class="op">(</span>gtk_application_window_new <span class="op">(</span>GTK_APPLICATION <span class="op">(</span>app<span class="op">)));</span></span>
<span id="cb10-33"><a href="#cb10-33"></a> gtk_window_set_title <span class="op">(</span>win<span class="op">,</span> <span class="st">&quot;menu2&quot;</span><span class="op">);</span></span>
<span id="cb10-34"><a href="#cb10-34"></a> gtk_window_set_default_size <span class="op">(</span>win<span class="op">,</span> <span class="dv">400</span><span class="op">,</span> <span class="dv">300</span><span class="op">);</span></span>
<span id="cb10-35"><a href="#cb10-35"></a></span>
<span id="cb10-36"><a href="#cb10-36"></a> GtkWidget <span class="op">*</span>lb <span class="op">=</span> gtk_label_new <span class="op">(</span>NULL<span class="op">);</span></span>
<span id="cb10-37"><a href="#cb10-37"></a> gtk_widget_add_css_class <span class="op">(</span>lb<span class="op">,</span> <span class="st">&quot;lb&quot;</span><span class="op">);</span> <span class="co">/* the class is used by CSS Selector */</span></span>
<span id="cb10-38"><a href="#cb10-38"></a> gtk_window_set_child <span class="op">(</span>win<span class="op">,</span> lb<span class="op">);</span></span>
<span id="cb10-39"><a href="#cb10-39"></a></span>
<span id="cb10-40"><a href="#cb10-40"></a> GSimpleAction <span class="op">*</span>act_fullscreen</span>
<span id="cb10-41"><a href="#cb10-41"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">&quot;fullscreen&quot;</span><span class="op">,</span> NULL<span class="op">,</span> g_variant_new_boolean <span class="op">(</span>FALSE<span class="op">));</span></span>
<span id="cb10-42"><a href="#cb10-42"></a> g_signal_connect <span class="op">(</span>act_fullscreen<span class="op">,</span> <span class="st">&quot;change-state&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>fullscreen_changed<span class="op">),</span> win<span class="op">);</span></span>
<span id="cb10-43"><a href="#cb10-43"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_fullscreen<span class="op">));</span></span>
<span id="cb10-44"><a href="#cb10-44"></a></span>
<span id="cb10-45"><a href="#cb10-45"></a> gtk_application_window_set_show_menubar <span class="op">(</span>GTK_APPLICATION_WINDOW <span class="op">(</span>win<span class="op">),</span> TRUE<span class="op">);</span></span>
<span id="cb10-46"><a href="#cb10-46"></a></span>
<span id="cb10-47"><a href="#cb10-47"></a> gtk_window_present <span class="op">(</span>win<span class="op">);</span></span>
<span id="cb10-48"><a href="#cb10-48"></a><span class="op">}</span></span>
<span id="cb10-49"><a href="#cb10-49"></a></span>
<span id="cb10-50"><a href="#cb10-50"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb10-51"><a href="#cb10-51"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>app<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-52"><a href="#cb10-52"></a> GVariantType <span class="op">*</span>vtype <span class="op">=</span> g_variant_type_new<span class="op">(</span><span class="st">&quot;s&quot;</span><span class="op">);</span></span>
<span id="cb10-53"><a href="#cb10-53"></a> GSimpleAction <span class="op">*</span>act_color</span>
<span id="cb10-54"><a href="#cb10-54"></a> <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">&quot;color&quot;</span><span class="op">,</span> vtype<span class="op">,</span> g_variant_new_string <span class="op">(</span><span class="st">&quot;red&quot;</span><span class="op">));</span></span>
<span id="cb10-55"><a href="#cb10-55"></a> g_variant_type_free <span class="op">(</span>vtype<span class="op">);</span></span>
<span id="cb10-56"><a href="#cb10-56"></a> GSimpleAction <span class="op">*</span>act_quit</span>
<span id="cb10-57"><a href="#cb10-57"></a> <span class="op">=</span> g_simple_action_new <span class="op">(</span><span class="st">&quot;quit&quot;</span><span class="op">,</span> NULL<span class="op">);</span></span>
<span id="cb10-58"><a href="#cb10-58"></a> g_signal_connect <span class="op">(</span>act_color<span class="op">,</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>color_activated<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb10-59"><a href="#cb10-59"></a> g_signal_connect_swapped <span class="op">(</span>act_quit<span class="op">,</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>g_application_quit<span class="op">),</span> app<span class="op">);</span></span>
<span id="cb10-60"><a href="#cb10-60"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>app<span class="op">),</span> G_ACTION <span class="op">(</span>act_color<span class="op">));</span></span>
<span id="cb10-61"><a href="#cb10-61"></a> g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>app<span class="op">),</span> G_ACTION <span class="op">(</span>act_quit<span class="op">));</span></span>
<span id="cb10-62"><a href="#cb10-62"></a></span>
<span id="cb10-63"><a href="#cb10-63"></a> GMenu <span class="op">*</span>menubar <span class="op">=</span> g_menu_new <span class="op">();</span></span>
<span id="cb10-64"><a href="#cb10-64"></a> GMenu <span class="op">*</span>menu <span class="op">=</span> g_menu_new <span class="op">();</span></span>
<span id="cb10-65"><a href="#cb10-65"></a> GMenu <span class="op">*</span>section1 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
<span id="cb10-66"><a href="#cb10-66"></a> GMenu <span class="op">*</span>section2 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
<span id="cb10-67"><a href="#cb10-67"></a> GMenu <span class="op">*</span>section3 <span class="op">=</span> g_menu_new <span class="op">();</span></span>
<span id="cb10-68"><a href="#cb10-68"></a> GMenuItem <span class="op">*</span>menu_item_fullscreen <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Full Screen&quot;</span><span class="op">,</span> <span class="st">&quot;win.fullscreen&quot;</span><span class="op">);</span></span>
<span id="cb10-69"><a href="#cb10-69"></a> GMenuItem <span class="op">*</span>menu_item_red <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Red&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::red&quot;</span><span class="op">);</span></span>
<span id="cb10-70"><a href="#cb10-70"></a> GMenuItem <span class="op">*</span>menu_item_green <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Green&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::green&quot;</span><span class="op">);</span></span>
<span id="cb10-71"><a href="#cb10-71"></a> GMenuItem <span class="op">*</span>menu_item_blue <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Blue&quot;</span><span class="op">,</span> <span class="st">&quot;app.color::blue&quot;</span><span class="op">);</span></span>
<span id="cb10-72"><a href="#cb10-72"></a> GMenuItem <span class="op">*</span>menu_item_quit <span class="op">=</span> g_menu_item_new <span class="op">(</span><span class="st">&quot;Quit&quot;</span><span class="op">,</span> <span class="st">&quot;app.quit&quot;</span><span class="op">);</span></span>
<span id="cb10-73"><a href="#cb10-73"></a></span>
<span id="cb10-74"><a href="#cb10-74"></a> g_menu_append_item <span class="op">(</span>section1<span class="op">,</span> menu_item_fullscreen<span class="op">);</span></span>
<span id="cb10-75"><a href="#cb10-75"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_red<span class="op">);</span></span>
<span id="cb10-76"><a href="#cb10-76"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_green<span class="op">);</span></span>
<span id="cb10-77"><a href="#cb10-77"></a> g_menu_append_item <span class="op">(</span>section2<span class="op">,</span> menu_item_blue<span class="op">);</span></span>
<span id="cb10-78"><a href="#cb10-78"></a> g_menu_append_item <span class="op">(</span>section3<span class="op">,</span> menu_item_quit<span class="op">);</span></span>
<span id="cb10-79"><a href="#cb10-79"></a> g_object_unref <span class="op">(</span>menu_item_red<span class="op">);</span></span>
<span id="cb10-80"><a href="#cb10-80"></a> g_object_unref <span class="op">(</span>menu_item_green<span class="op">);</span></span>
<span id="cb10-81"><a href="#cb10-81"></a> g_object_unref <span class="op">(</span>menu_item_blue<span class="op">);</span></span>
<span id="cb10-82"><a href="#cb10-82"></a> g_object_unref <span class="op">(</span>menu_item_fullscreen<span class="op">);</span></span>
<span id="cb10-83"><a href="#cb10-83"></a> g_object_unref <span class="op">(</span>menu_item_quit<span class="op">);</span></span>
<span id="cb10-84"><a href="#cb10-84"></a></span>
<span id="cb10-85"><a href="#cb10-85"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> NULL<span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section1<span class="op">));</span></span>
<span id="cb10-86"><a href="#cb10-86"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> <span class="st">&quot;Color&quot;</span><span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section2<span class="op">));</span></span>
<span id="cb10-87"><a href="#cb10-87"></a> g_menu_append_section <span class="op">(</span>menu<span class="op">,</span> NULL<span class="op">,</span> G_MENU_MODEL <span class="op">(</span>section3<span class="op">));</span></span>
<span id="cb10-88"><a href="#cb10-88"></a> g_menu_append_submenu <span class="op">(</span>menubar<span class="op">,</span> <span class="st">&quot;Menu&quot;</span><span class="op">,</span> G_MENU_MODEL <span class="op">(</span>menu<span class="op">));</span></span>
<span id="cb10-89"><a href="#cb10-89"></a> g_object_unref <span class="op">(</span>section1<span class="op">);</span></span>
<span id="cb10-90"><a href="#cb10-90"></a> g_object_unref <span class="op">(</span>section2<span class="op">);</span></span>
<span id="cb10-91"><a href="#cb10-91"></a> g_object_unref <span class="op">(</span>section3<span class="op">);</span></span>
<span id="cb10-92"><a href="#cb10-92"></a> g_object_unref <span class="op">(</span>menu<span class="op">);</span></span>
<span id="cb10-93"><a href="#cb10-93"></a></span>
<span id="cb10-94"><a href="#cb10-94"></a> gtk_application_set_menubar <span class="op">(</span>GTK_APPLICATION <span class="op">(</span>app<span class="op">),</span> G_MENU_MODEL <span class="op">(</span>menubar<span class="op">));</span></span>
<span id="cb10-95"><a href="#cb10-95"></a></span>
<span id="cb10-96"><a href="#cb10-96"></a> provider <span class="op">=</span> gtk_css_provider_new <span class="op">();</span></span>
<span id="cb10-97"><a href="#cb10-97"></a> <span class="co">/* Initialize the css data */</span></span>
<span id="cb10-98"><a href="#cb10-98"></a> gtk_css_provider_load_from_data <span class="op">(</span>provider<span class="op">,</span> <span class="st">&quot;label.lb {background-color: red;}&quot;</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb10-99"><a href="#cb10-99"></a> <span class="co">/* Add CSS to the default GdkDisplay. */</span></span>
<span id="cb10-100"><a href="#cb10-100"></a> gtk_style_context_add_provider_for_display <span class="op">(</span>gdk_display_get_default <span class="op">(),</span></span>
<span id="cb10-101"><a href="#cb10-101"></a> GTK_STYLE_PROVIDER <span class="op">(</span>provider<span class="op">),</span> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION<span class="op">);</span></span>
<span id="cb10-102"><a href="#cb10-102"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">&quot;shutdown&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_shutdown<span class="op">),</span> provider<span class="op">);</span></span>
<span id="cb10-103"><a href="#cb10-103"></a> g_object_unref <span class="op">(</span>provider<span class="op">);</span> <span class="co">/* release provider, but it&#39;s still alive because the display owns it */</span></span>
<span id="cb10-104"><a href="#cb10-104"></a><span class="op">}</span></span>
<span id="cb10-105"><a href="#cb10-105"></a></span>
<span id="cb10-106"><a href="#cb10-106"></a><span class="pp">#define APPLICATION_ID &quot;com.github.ToshioCP.menu2&quot;</span></span>
<span id="cb10-107"><a href="#cb10-107"></a></span>
<span id="cb10-108"><a href="#cb10-108"></a><span class="dt">int</span></span>
<span id="cb10-109"><a href="#cb10-109"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-110"><a href="#cb10-110"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
<span id="cb10-111"><a href="#cb10-111"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
<span id="cb10-112"><a href="#cb10-112"></a></span>
<span id="cb10-113"><a href="#cb10-113"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
<span id="cb10-114"><a href="#cb10-114"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">&quot;startup&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb10-115"><a href="#cb10-115"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb10-116"><a href="#cb10-116"></a></span>
<span id="cb10-117"><a href="#cb10-117"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
<span id="cb10-118"><a href="#cb10-118"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
<span id="cb10-119"><a href="#cb10-119"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
<span id="cb10-120"><a href="#cb10-120"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>6-23: Action signal handlers.</li>
<li>25-28: The handler <code>app_shutdown</code> is called when the
application quits. It removes the provider from the display.</li>
<li>30-48: An activate signal handler.</li>
<li>32-34: A new window is created and assigned to <code>win</code>. Its
title and default size are set to “menu2” and 400x300 respectively.</li>
<li>36-38: A new label is created and assigned to <code>lb</code> The
label is given a CSS class “lb”. It is added to <code>win</code> as a
child.</li>
<li>40-43: A toggle action is created and assigned to
<code>act_fullscreen</code>. Its connected to the signal handler
<code>fullscreen_changed</code>. Its added to the window, so the action
scope is “win”. So, if there are two or more windows, the actions are
created two or more.</li>
<li>45: The function
<code>gtk_application_window_set_show_menubar</code> adds a menubar to
the window.</li>
<li>47: Shows the window.</li>
<li>50-104: A startup signal handler.</li>
<li>52-61: Two actions <code>act_color</code> and <code>act_quit</code>
are created. These actions exists only one because the startup handler
is called once. They are connected to their handlers and added to the
application. Their scopes are “app”.</li>
<li>63-92: Menus are built.</li>
<li>94: The menubar is added to the application.</li>
<li>96-103: A CSS provider is created with the CSS data and added to the
default display. The “shutdown” signal on the application is connected
to a handler “app_shutdown”. So, the provider is removed from the
display and freed when the application quits.</li>
</ul>
<h2 id="compile">Compile</h2>
<p>Change your current directory to <code>src/menu</code>.</p>
<pre><code>$ comp menu2
$./a.out</code></pre>
<p>Then, you will see a window and the background color of the content
is red. You can change the size to maximum and change back to the
original size. You can change the background color to green or blue.</p>
<p>If you run the second application during the first application is
running, another window will appear in the same screen. Both of the
window have the same background color. Because the
<code>act_color</code> action has “app” scope and the CSS is applied to
the default display shared by the windows.</p>
<pre><code>$ ./a.out &amp; # Run the first application
[1] 82113
$ ./a.out # Run the second application
$ </code></pre>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>