]> Pileus Git - ~andy/gtk/blob - gtk/gtkapplicationwindow.c
Add an example
[~andy/gtk] / gtk / gtkapplicationwindow.c
1 /*
2  * Copyright © 2011 Canonical Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include "gtkapplicationwindow.h"
25
26 #include "gtkmodelmenu.h"
27 #include "gactionmuxer.h"
28 #include "gtkintl.h"
29
30 /**
31  * SECTION:gtkapplicationwindow
32  * @title: GtkApplicationWindow
33  * @short_description: GtkWindow subclass with GtkApplication support
34  *
35  * GtkApplicationWindow is a #GtkWindow subclass that offers some
36  * extra functionality for better integration with #GtkApplication
37  * features.  Notably, it can handle both the application menu as well
38  * as the menubar.  See g_application_set_app_menu() and
39  * g_application_set_menubar().
40  *
41  * This class implements the #GActionGroup and #GActionMap interfaces,
42  * to let you add window-specific actions that will be exported by the
43  * associated #GtkApplication, together with its application-wide
44  * actions.  Window-specific actions are prefixed with the "win."
45  * prefix and application-wide actions are prefixed with the "app."
46  * prefix.  Actions must be addressed with the prefixed name when
47  * referring to them from a #GMenuModel.
48  *
49  * If the desktop environment does not display the application menu
50  * as part of the desktop shell, then #GApplicationWindow will
51  * automatically show the menu as part of a menubar. This behaviour
52  * can be overridden with the #GtkApplicationWindow:show-menubar
53  * property.
54  *
55  * <example><title>A GtkApplicationWindow with a menubar</title>
56  * <programlisting><![CDATA[
57  * app = gtk_application_new ();
58  *
59  * builder = gtk_builder_new ();
60  * gtk_builder_add_from_string (builder,
61  *     "<interface>"
62  *     "  <menu id='menubar'>"
63  *     "    <submenu label='_Edit'>"
64  *     "      <item label='_Copy' action='win.copy'/>"
65  *     "      <item label='_Paste' action='win.paste'/>"
66  *     "    </submenu>"
67  *     "  </menu>"
68  *     "</interface>");
69  * g_application_set_menubar (G_APPLICATION (app),
70  *                            G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
71  * g_object_unref (builder);
72  *
73  * ...
74  *
75  * window = gtk_application_window_new (app);
76  * ]]>
77  * </programlisting>
78  * </example>
79  */
80 struct _GtkApplicationWindowPrivate
81 {
82   GSimpleActionGroup *actions;
83   GtkWidget *menubar;
84
85   GMenu *app_menu_section;
86   GMenu *menubar_section;
87   gboolean show_menubar;
88 };
89
90 static void
91 gtk_application_window_update_menubar (GtkApplicationWindow *window)
92 {
93   gboolean should_have_menubar;
94   gboolean have_menubar;
95
96   have_menubar = window->priv->menubar != NULL;
97
98   should_have_menubar = window->priv->show_menubar &&
99                         (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) ||
100                          g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)));
101
102   if (have_menubar && !should_have_menubar)
103     {
104       gtk_widget_unparent (window->priv->menubar);
105       window->priv->menubar = NULL;
106
107       gtk_widget_queue_resize (GTK_WIDGET (window));
108     }
109
110   if (!have_menubar && should_have_menubar)
111     {
112       GActionMuxer *muxer;
113       GMenu *combined;
114
115       muxer = g_action_muxer_new ();
116       g_action_muxer_insert (muxer, "app", G_ACTION_GROUP (gtk_window_get_application (GTK_WINDOW (window))));
117       g_action_muxer_insert (muxer, "win", G_ACTION_GROUP (window));
118
119       combined = g_menu_new ();
120       g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section));
121       g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section));
122
123       window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), G_ACTION_OBSERVABLE (muxer));
124       gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window));
125       gtk_widget_show_all (window->priv->menubar);
126       g_object_unref (combined);
127       g_object_unref (muxer);
128
129       gtk_widget_queue_resize (GTK_WIDGET (window));
130     }
131 }
132
133 static void
134 gtk_application_window_update_shell_shows_app_menu (GtkApplicationWindow *window,
135                                                     GtkSettings          *settings)
136 {
137   gboolean shown_by_shell;
138
139   g_object_get (settings, "gtk-shell-shows-app-menu", &shown_by_shell, NULL);
140
141   if (shown_by_shell)
142     {
143       /* the shell shows it, so don't show it locally */
144       if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) != 0)
145         g_menu_remove (window->priv->app_menu_section, 0);
146     }
147   else
148     {
149       /* the shell does not show it, so make sure we show it */
150       if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) == 0)
151         {
152           GMenuModel *app_menu;
153
154           app_menu = g_application_get_app_menu (G_APPLICATION (gtk_window_get_application (GTK_WINDOW (window))));
155
156           if (app_menu != NULL)
157             g_menu_append_submenu (window->priv->app_menu_section, _("Application"), app_menu);
158         }
159     }
160 }
161
162 static void
163 gtk_application_window_update_shell_shows_menubar (GtkApplicationWindow *window,
164                                                    GtkSettings          *settings)
165 {
166   gboolean shown_by_shell;
167
168   g_object_get (settings, "gtk-shell-shows-menubar", &shown_by_shell, NULL);
169
170   if (shown_by_shell)
171     {
172       /* the shell shows it, so don't show it locally */
173       if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)) != 0)
174         g_menu_remove (window->priv->menubar_section, 0);
175     }
176   else
177     {
178       /* the shell does not show it, so make sure we show it */
179       if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)) == 0)
180         {
181           GMenuModel *menubar;
182
183           menubar = g_application_get_menubar (G_APPLICATION (gtk_window_get_application (GTK_WINDOW (window))));
184
185           if (menubar != NULL)
186             g_menu_append_section (window->priv->menubar_section, NULL, menubar);
187         }
188     }
189 }
190
191 static void
192 gtk_application_window_shell_shows_app_menu_changed (GObject    *object,
193                                                      GParamSpec *pspec,
194                                                      gpointer    user_data)
195 {
196   GtkApplicationWindow *window = user_data;
197
198   gtk_application_window_update_shell_shows_app_menu (window, GTK_SETTINGS (object));
199   gtk_application_window_update_menubar (window);
200 }
201
202 static void
203 gtk_application_window_shell_shows_menubar_changed (GObject    *object,
204                                                     GParamSpec *pspec,
205                                                     gpointer    user_data)
206 {
207   GtkApplicationWindow *window = user_data;
208
209   gtk_application_window_update_shell_shows_menubar (window, GTK_SETTINGS (object));
210   gtk_application_window_update_menubar (window);
211 }
212
213 static gchar **
214 gtk_application_window_list_actions (GActionGroup *group)
215 {
216   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);
217
218   return g_action_group_list_actions (G_ACTION_GROUP (window->priv->actions));
219 }
220
221 static gboolean
222 gtk_application_window_query_action (GActionGroup        *group,
223                                      const gchar         *action_name,
224                                      gboolean            *enabled,
225                                      const GVariantType **parameter_type,
226                                      const GVariantType **state_type,
227                                      GVariant           **state_hint,
228                                      GVariant           **state)
229 {
230   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);
231
232   return g_action_group_query_action (G_ACTION_GROUP (window->priv->actions),
233                                       action_name, enabled, parameter_type, state_type, state_hint, state);
234 }
235
236 static void
237 gtk_application_window_activate_action (GActionGroup *group,
238                                         const gchar  *action_name,
239                                         GVariant     *parameter)
240 {
241   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);
242
243   return g_action_group_activate_action (G_ACTION_GROUP (window->priv->actions), action_name, parameter);
244 }
245
246 static void
247 gtk_application_window_change_action_state (GActionGroup *group,
248                                             const gchar  *action_name,
249                                             GVariant     *state)
250 {
251   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);
252
253   return g_action_group_change_action_state (G_ACTION_GROUP (window->priv->actions), action_name, state);
254 }
255
256 static GAction *
257 gtk_application_window_lookup_action (GActionMap  *action_map,
258                                       const gchar *action_name)
259 {
260   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);
261
262   return g_action_map_lookup_action (G_ACTION_MAP (window->priv->actions), action_name);
263 }
264
265 static void
266 gtk_application_window_add_action (GActionMap *action_map,
267                                    GAction    *action)
268 {
269   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);
270
271   g_action_map_add_action (G_ACTION_MAP (window->priv->actions), action);
272 }
273
274 static void
275 gtk_application_window_remove_action (GActionMap  *action_map,
276                                       const gchar *action_name)
277 {
278   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);
279
280   g_action_map_remove_action (G_ACTION_MAP (window->priv->actions), action_name);
281 }
282
283 static void
284 gtk_application_window_group_iface_init (GActionGroupInterface *iface)
285 {
286   iface->list_actions = gtk_application_window_list_actions;
287   iface->query_action = gtk_application_window_query_action;
288   iface->activate_action = gtk_application_window_activate_action;
289   iface->change_action_state = gtk_application_window_change_action_state;
290 }
291
292 static void
293 gtk_application_window_map_iface_init (GActionMapInterface *iface)
294 {
295   iface->lookup_action = gtk_application_window_lookup_action;
296   iface->add_action = gtk_application_window_add_action;
297   iface->remove_action = gtk_application_window_remove_action;
298 }
299
300 G_DEFINE_TYPE_WITH_CODE (GtkApplicationWindow, gtk_application_window, GTK_TYPE_WINDOW,
301                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, gtk_application_window_group_iface_init)
302                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_MAP, gtk_application_window_map_iface_init))
303
304 enum {
305   PROP_0,
306   PROP_SHOW_MENUBAR,
307   N_PROPS
308 };
309 static GParamSpec *gtk_application_window_properties[N_PROPS];
310
311 static void
312 gtk_application_window_real_get_preferred_height (GtkWidget *widget,
313                                                   gint      *minimum_height,
314                                                   gint      *natural_height)
315 {
316   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
317
318   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
319     ->get_preferred_height (widget, minimum_height, natural_height);
320
321   if (window->priv->menubar != NULL)
322     {
323       gint menubar_min_height, menubar_nat_height;
324
325       gtk_widget_get_preferred_height (window->priv->menubar, &menubar_min_height, &menubar_nat_height);
326       *minimum_height += menubar_min_height;
327       *natural_height += menubar_nat_height;
328     }
329 }
330
331 static void
332 gtk_application_window_real_get_preferred_height_for_width (GtkWidget *widget,
333                                                             gint       width,
334                                                             gint      *minimum_height,
335                                                             gint      *natural_height)
336 {
337   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
338
339   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
340     ->get_preferred_height_for_width (widget, width, minimum_height, natural_height);
341
342   if (window->priv->menubar != NULL)
343     {
344       gint menubar_min_height, menubar_nat_height;
345
346       gtk_widget_get_preferred_height_for_width (window->priv->menubar, width, &menubar_min_height, &menubar_nat_height);
347       *minimum_height += menubar_min_height;
348       *natural_height += menubar_nat_height;
349     }
350 }
351
352 static void
353 gtk_application_window_real_get_preferred_width (GtkWidget *widget,
354                                                  gint      *minimum_width,
355                                                  gint      *natural_width)
356 {
357   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
358
359   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
360     ->get_preferred_width (widget, minimum_width, natural_width);
361
362   if (window->priv->menubar != NULL)
363     {
364       gint menubar_min_width, menubar_nat_width;
365
366       gtk_widget_get_preferred_width (window->priv->menubar, &menubar_min_width, &menubar_nat_width);
367       *minimum_width = MAX (*minimum_width, menubar_min_width);
368       *natural_width = MAX (*natural_width, menubar_nat_width);
369     }
370 }
371
372 static void
373 gtk_application_window_real_get_preferred_width_for_height (GtkWidget *widget,
374                                                             gint       height,
375                                                             gint      *minimum_width,
376                                                             gint      *natural_width)
377 {
378   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
379
380   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
381     ->get_preferred_width_for_height (widget, height, minimum_width, natural_width);
382
383   if (window->priv->menubar != NULL)
384     {
385       gint menubar_min_width, menubar_nat_width;
386
387       gtk_widget_get_preferred_width_for_height (window->priv->menubar, height, &menubar_min_width, &menubar_nat_width);
388       *minimum_width = MAX (*minimum_width, menubar_min_width);
389       *natural_width = MAX (*natural_width, menubar_nat_width);
390     }
391 }
392
393 static void
394 gtk_application_window_real_size_allocate (GtkWidget     *widget,
395                                            GtkAllocation *allocation)
396 {
397   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
398
399   if (window->priv->menubar != NULL)
400     {
401       GtkAllocation menubar_allocation = *allocation;
402       gint menubar_min_height, menubar_nat_height;
403       GtkWidget *child;
404
405       gtk_widget_get_preferred_height_for_width (window->priv->menubar, allocation->width, &menubar_min_height, &menubar_nat_height);
406
407       menubar_allocation.height = menubar_min_height;
408       gtk_widget_size_allocate (window->priv->menubar, &menubar_allocation);
409
410       child = gtk_bin_get_child (GTK_BIN (window));
411       if (child != NULL && gtk_widget_get_visible (child))
412         {
413           GtkAllocation child_allocation = *allocation;
414           gint border_width;
415
416           child_allocation.height = MAX (1, child_allocation.height - menubar_min_height);
417
418           border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
419           child_allocation.x += border_width;
420           child_allocation.y += border_width + menubar_min_height;
421           child_allocation.width -= border_width * 2;
422           child_allocation.height -= border_width * 2 - menubar_min_height;
423           gtk_widget_size_allocate (child, &child_allocation);
424         }
425
426       gtk_widget_set_allocation (widget, allocation);
427     }
428   else
429     GTK_WIDGET_CLASS (gtk_application_window_parent_class)
430       ->size_allocate (widget, allocation);
431 }
432
433 static void
434 gtk_application_window_real_realize (GtkWidget *widget)
435 {
436   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
437   GtkSettings *settings;
438
439   settings = gtk_widget_get_settings (widget);
440
441   g_signal_connect (settings, "notify::gtk-shell-shows-app-menu",
442                     G_CALLBACK (gtk_application_window_shell_shows_app_menu_changed), window);
443   g_signal_connect (settings, "notify::gtk-shell-shows-menubar",
444                     G_CALLBACK (gtk_application_window_shell_shows_menubar_changed), window);
445
446   gtk_application_window_update_shell_shows_app_menu (window, settings);
447   gtk_application_window_update_shell_shows_menubar (window, settings);
448   gtk_application_window_update_menubar (window);
449
450   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
451     ->realize (widget);
452 }
453
454 static void
455 gtk_application_window_real_unrealize (GtkWidget *widget)
456 {
457   GtkSettings *settings;
458
459   settings = gtk_widget_get_settings (widget);
460
461   g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_app_menu_changed, widget);
462   g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_menubar_changed, widget);
463
464   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
465     ->unrealize (widget);
466 }
467
468 static void
469 gtk_application_window_real_map (GtkWidget *widget)
470 {
471   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
472
473   /* XXX could eliminate this by tweaking gtk_window_map */
474   if (window->priv->menubar)
475     gtk_widget_map (window->priv->menubar);
476
477   GTK_WIDGET_CLASS (gtk_application_window_parent_class)
478     ->map (widget);
479 }
480
481 static void
482 gtk_application_window_real_forall_internal (GtkContainer *container,
483                                              gboolean      include_internal,
484                                              GtkCallback   callback,
485                                              gpointer      user_data)
486 {
487   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (container);
488
489   if (window->priv->menubar)
490     callback (window->priv->menubar, user_data);
491
492   GTK_CONTAINER_CLASS (gtk_application_window_parent_class)
493     ->forall (container, include_internal, callback, user_data);
494 }
495
496
497 static void
498 gtk_application_window_get_property (GObject    *object,
499                                      guint       prop_id,
500                                      GValue     *value,
501                                      GParamSpec *pspec)
502 {
503   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);
504
505   switch (prop_id)
506     {
507     case PROP_SHOW_MENUBAR:
508       g_value_set_boolean (value, window->priv->show_menubar);
509       break;
510
511     default:
512       g_assert_not_reached ();
513     }
514 }
515
516 static void
517 gtk_application_window_set_property (GObject      *object,
518                                      guint         prop_id,
519                                      const GValue *value,
520                                      GParamSpec   *pspec)
521 {
522   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);
523
524   switch (prop_id)
525     {
526     case PROP_SHOW_MENUBAR:
527       gtk_application_window_set_show_menubar (window, g_value_get_boolean (value));
528       break;
529
530     default:
531       g_assert_not_reached ();
532     }
533 }
534
535 static void
536 gtk_application_window_dispose (GObject *object)
537 {
538   GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);
539
540   if (window->priv->menubar)
541     {
542       gtk_widget_unparent (window->priv->menubar);
543       window->priv->menubar = NULL;
544     }
545
546   g_clear_object (&window->priv->app_menu_section);
547   g_clear_object (&window->priv->menubar_section);
548   g_clear_object (&window->priv->actions);
549
550   G_OBJECT_CLASS (gtk_application_window_parent_class)
551     ->dispose (object);
552 }
553
554 static void
555 gtk_application_window_init (GtkApplicationWindow *window)
556 {
557   window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, GTK_TYPE_APPLICATION_WINDOW, GtkApplicationWindowPrivate);
558
559   window->priv->actions = g_simple_action_group_new ();
560   window->priv->app_menu_section = g_menu_new ();
561   window->priv->menubar_section = g_menu_new ();
562
563   /* window->priv->actions is the one and only ref on the group, so when
564    * we dispose, the action group will die, disconnecting all signals.
565    */
566   g_signal_connect_swapped (window->priv->actions, "action-added",
567                             G_CALLBACK (g_action_group_action_added), window);
568   g_signal_connect_swapped (window->priv->actions, "action-enabled-changed",
569                             G_CALLBACK (g_action_group_action_enabled_changed), window);
570   g_signal_connect_swapped (window->priv->actions, "action-state-changed",
571                             G_CALLBACK (g_action_group_action_state_changed), window);
572   g_signal_connect_swapped (window->priv->actions, "action-removed",
573                             G_CALLBACK (g_action_group_action_removed), window);
574 }
575
576 static void
577 gtk_application_window_class_init (GtkApplicationWindowClass *class)
578 {
579   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
580   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
581   GObjectClass *object_class = G_OBJECT_CLASS (class);
582
583   container_class->forall = gtk_application_window_real_forall_internal;
584   widget_class->get_preferred_height = gtk_application_window_real_get_preferred_height;
585   widget_class->get_preferred_height_for_width = gtk_application_window_real_get_preferred_height_for_width;
586   widget_class->get_preferred_width = gtk_application_window_real_get_preferred_width;
587   widget_class->get_preferred_width_for_height = gtk_application_window_real_get_preferred_width_for_height;
588   widget_class->size_allocate = gtk_application_window_real_size_allocate;
589   widget_class->realize = gtk_application_window_real_realize;
590   widget_class->unrealize = gtk_application_window_real_unrealize;
591   widget_class->map = gtk_application_window_real_map;
592   object_class->get_property = gtk_application_window_get_property;
593   object_class->set_property = gtk_application_window_set_property;
594   object_class->dispose = gtk_application_window_dispose;
595
596   /**
597    * GtkApplicationWindow:show-menubar:
598    *
599    * If this property is %TRUE, the window will display a menubar
600    * that includes the app menu and menubar, unless these are
601    * shown by the desktop shell. See g_application_set_app_menu()
602    * and g_application_set_menubar().
603    *
604    * If %FALSE, the window will not display a menubar, regardless
605    * of whether the desktop shell is showing the menus or not.
606    */
607   gtk_application_window_properties[PROP_SHOW_MENUBAR] =
608     g_param_spec_boolean ("show-menubar",
609                           P_("Show a menubar"),
610                           P_("TRUE if the window should show a "
611                              "menubar at the top of the window"),
612                           TRUE, G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
613   g_object_class_install_properties (object_class, N_PROPS, gtk_application_window_properties);
614   g_type_class_add_private (class, sizeof (GtkApplicationWindowPrivate));
615 }
616
617 /**
618  * gtk_application_window_new:
619  * @application: a #GtkApplication
620  *
621  * Creates a new #GtkApplicationWindow.
622  *
623  * Returns: a newly created #GtkApplicationWindow
624  *
625  * Since: 3.4
626  */
627 GtkWidget *
628 gtk_application_window_new (GtkApplication *application)
629 {
630   g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
631
632   return g_object_new (GTK_TYPE_APPLICATION_WINDOW,
633                        "application", application,
634                        NULL);
635 }
636
637 /**
638  * gtk_application_window_get_show_menubar:
639  * @window: a #GtkApplicationWindow
640  *
641  * Returns whether the window will display a menubar for the app menu
642  * and menubar as needed.
643  *
644  * Returns: %TRUE if @window will display a menubar when needed
645  *
646  * Since: 3.4
647  */
648 gboolean
649 gtk_application_window_get_show_menubar (GtkApplicationWindow *window)
650 {
651   return window->priv->show_menubar;
652 }
653
654 /**
655  * gtk_application_window_set_show_menubar:
656  * @window: a #GtkApplicationWindow
657  * @show_menubar: whether to show a menubar when needed
658  *
659  * Sets whether the window will display a menubar for the app menu
660  * and menubar as needed.
661  *
662  * Since: 3.4
663  */
664 void
665 gtk_application_window_set_show_menubar (GtkApplicationWindow *window,
666                                          gboolean              show_menubar)
667 {
668   g_return_if_fail (GTK_IS_APPLICATION_WINDOW (window));
669
670   show_menubar = !!show_menubar;
671
672   if (window->priv->show_menubar != show_menubar)
673     {
674       window->priv->show_menubar = show_menubar;
675
676       gtk_application_window_update_menubar (window);
677
678       g_object_notify_by_pspec (G_OBJECT (window), gtk_application_window_properties[PROP_SHOW_MENUBAR]);
679     }
680 }