gtkapplicationwindow.c 22.3 KB
Newer Older
Allison Karlitskaya's avatar
Allison Karlitskaya committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright © 2011 Canonical Limited
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the licence, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Ryan Lortie <desrt@desrt.ca>
 */

#include "config.h"

#include "gtkapplicationwindow.h"

26
#include "gtkmodelmenu.h"
Allison Karlitskaya's avatar
Allison Karlitskaya committed
27
#include "gactionmuxer.h"
Matthias Clasen's avatar
Matthias Clasen committed
28
#include "gtkintl.h"
Allison Karlitskaya's avatar
Allison Karlitskaya committed
29

Matthias Clasen's avatar
Matthias Clasen committed
30 31 32 33 34
/**
 * SECTION:gtkapplicationwindow
 * @title: GtkApplicationWindow
 * @short_description: GtkWindow subclass with GtkApplication support
 *
35 36 37 38 39 40 41 42 43 44 45 46 47
 * GtkApplicationWindow is a #GtkWindow subclass that offers some
 * extra functionality for better integration with #GtkApplication
 * features.  Notably, it can handle both the application menu as well
 * as the menubar.  See g_application_set_app_menu() and
 * g_application_set_menubar().
 *
 * This class implements the #GActionGroup and #GActionMap interfaces,
 * to let you add window-specific actions that will be exported by the
 * associated #GtkApplication, together with its application-wide
 * actions.  Window-specific actions are prefixed with the "win."
 * prefix and application-wide actions are prefixed with the "app."
 * prefix.  Actions must be addressed with the prefixed name when
 * referring to them from a #GMenuModel.
Matthias Clasen's avatar
Matthias Clasen committed
48 49 50 51 52 53 54
 *
 * If the desktop environment does not display the application menu
 * as part of the desktop shell, then #GApplicationWindow will
 * automatically show the menu as part of a menubar. This behaviour
 * can be overridden with the #GtkApplicationWindow:show-app-menu
 * property.
 */
Allison Karlitskaya's avatar
Allison Karlitskaya committed
55 56
struct _GtkApplicationWindowPrivate
{
57
  GSimpleActionGroup *actions;
58
  GtkWidget *menubar;
Allison Karlitskaya's avatar
Allison Karlitskaya committed
59

60 61 62
  GMenu *app_menu_section;
  GMenu *menubar_section;
  gboolean show_menubar;
Allison Karlitskaya's avatar
Allison Karlitskaya committed
63 64
};

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static void
gtk_application_window_update_menubar (GtkApplicationWindow *window)
{
  gboolean should_have_menubar;
  gboolean have_menubar;

  have_menubar = window->priv->menubar != NULL;

  should_have_menubar = window->priv->show_menubar &&
                        (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) ||
                         g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)));

  if (have_menubar && !should_have_menubar)
    {
      gtk_widget_unparent (window->priv->menubar);
      window->priv->menubar = NULL;

      gtk_widget_queue_resize (GTK_WIDGET (window));
    }

  if (!have_menubar && should_have_menubar)
    {
      GActionMuxer *muxer;
      GMenu *combined;

      muxer = g_action_muxer_new ();
      g_action_muxer_insert (muxer, "app", G_ACTION_GROUP (gtk_window_get_application (GTK_WINDOW (window))));
      g_action_muxer_insert (muxer, "win", G_ACTION_GROUP (window));

      combined = g_menu_new ();
      g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section));
      g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section));

98
      window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), G_ACTION_OBSERVABLE (muxer));
99 100 101 102 103 104 105 106
      gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window));
      gtk_widget_show_all (window->priv->menubar);
      g_object_unref (combined);
      g_object_unref (muxer);

      gtk_widget_queue_resize (GTK_WIDGET (window));
    }
}
107 108

static void
109 110
gtk_application_window_update_shell_shows_app_menu (GtkApplicationWindow *window,
                                                    GtkSettings          *settings)
111
{
112
  gboolean shown_by_shell;
113

114
  g_object_get (settings, "gtk-shell-shows-app-menu", &shown_by_shell, NULL);
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137

  if (shown_by_shell)
    {
      /* the shell shows it, so don't show it locally */
      if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) != 0)
        g_menu_remove (window->priv->app_menu_section, 0);
    }
  else
    {
      /* the shell does not show it, so make sure we show it */
      if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->app_menu_section)) == 0)
        {
          GMenuModel *app_menu;

          app_menu = g_application_get_app_menu (G_APPLICATION (gtk_window_get_application (GTK_WINDOW (window))));

          if (app_menu != NULL)
            g_menu_append_submenu (window->priv->app_menu_section, _("Application"), app_menu);
        }
    }
}

static void
138 139
gtk_application_window_update_shell_shows_menubar (GtkApplicationWindow *window,
                                                   GtkSettings          *settings)
140 141 142
{
  gboolean shown_by_shell;

143
  g_object_get (settings, "gtk-shell-shows-menubar", &shown_by_shell, NULL);
144 145 146 147 148 149 150 151

  if (shown_by_shell)
    {
      /* the shell shows it, so don't show it locally */
      if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)) != 0)
        g_menu_remove (window->priv->menubar_section, 0);
    }
  else
152
    {
153 154 155 156 157 158 159 160 161 162
      /* the shell does not show it, so make sure we show it */
      if (g_menu_model_get_n_items (G_MENU_MODEL (window->priv->menubar_section)) == 0)
        {
          GMenuModel *menubar;

          menubar = g_application_get_menubar (G_APPLICATION (gtk_window_get_application (GTK_WINDOW (window))));

          if (menubar != NULL)
            g_menu_append_section (window->priv->menubar_section, NULL, menubar);
        }
163
    }
164 165
}

166 167 168 169 170 171 172
static void
gtk_application_window_shell_shows_app_menu_changed (GObject    *object,
                                                     GParamSpec *pspec,
                                                     gpointer    user_data)
{
  GtkApplicationWindow *window = user_data;

173
  gtk_application_window_update_shell_shows_app_menu (window, GTK_SETTINGS (object));
174 175 176 177 178 179 180 181 182 183
  gtk_application_window_update_menubar (window);
}

static void
gtk_application_window_shell_shows_menubar_changed (GObject    *object,
                                                    GParamSpec *pspec,
                                                    gpointer    user_data)
{
  GtkApplicationWindow *window = user_data;

184
  gtk_application_window_update_shell_shows_menubar (window, GTK_SETTINGS (object));
185 186 187
  gtk_application_window_update_menubar (window);
}

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static gchar **
gtk_application_window_list_actions (GActionGroup *group)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);

  return g_action_group_list_actions (G_ACTION_GROUP (window->priv->actions));
}

static gboolean
gtk_application_window_query_action (GActionGroup        *group,
                                     const gchar         *action_name,
                                     gboolean            *enabled,
                                     const GVariantType **parameter_type,
                                     const GVariantType **state_type,
                                     GVariant           **state_hint,
                                     GVariant           **state)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);

  return g_action_group_query_action (G_ACTION_GROUP (window->priv->actions),
                                      action_name, enabled, parameter_type, state_type, state_hint, state);
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
static void
gtk_application_window_activate_action (GActionGroup *group,
                                        const gchar  *action_name,
                                        GVariant     *parameter)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);

  return g_action_group_activate_action (G_ACTION_GROUP (window->priv->actions), action_name, parameter);
}

static void
gtk_application_window_change_action_state (GActionGroup *group,
                                            const gchar  *action_name,
                                            GVariant     *state)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (group);

  return g_action_group_change_action_state (G_ACTION_GROUP (window->priv->actions), action_name, state);
}

231
static GAction *
Matthias Clasen's avatar
Matthias Clasen committed
232
gtk_application_window_lookup_action (GActionMap  *action_map,
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
                                      const gchar *action_name)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);

  return g_action_map_lookup_action (G_ACTION_MAP (window->priv->actions), action_name);
}

static void
gtk_application_window_add_action (GActionMap *action_map,
                                   GAction    *action)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);

  g_action_map_add_action (G_ACTION_MAP (window->priv->actions), action);
}

static void
gtk_application_window_remove_action (GActionMap  *action_map,
                                      const gchar *action_name)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (action_map);

  g_action_map_remove_action (G_ACTION_MAP (window->priv->actions), action_name);
}

static void
gtk_application_window_group_iface_init (GActionGroupInterface *iface)
{
  iface->list_actions = gtk_application_window_list_actions;
  iface->query_action = gtk_application_window_query_action;
263 264
  iface->activate_action = gtk_application_window_activate_action;
  iface->change_action_state = gtk_application_window_change_action_state;
265 266 267 268 269 270 271 272 273 274 275 276 277
}

static void
gtk_application_window_map_iface_init (GActionMapInterface *iface)
{
  iface->lookup_action = gtk_application_window_lookup_action;
  iface->add_action = gtk_application_window_add_action;
  iface->remove_action = gtk_application_window_remove_action;
}

G_DEFINE_TYPE_WITH_CODE (GtkApplicationWindow, gtk_application_window, GTK_TYPE_WINDOW,
                         G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, gtk_application_window_group_iface_init)
                         G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_MAP, gtk_application_window_map_iface_init))
Allison Karlitskaya's avatar
Allison Karlitskaya committed
278 279 280

enum {
  PROP_0,
281
  PROP_SHOW_MENUBAR,
Allison Karlitskaya's avatar
Allison Karlitskaya committed
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
  N_PROPS
};
static GParamSpec *gtk_application_window_properties[N_PROPS];

static void
gtk_application_window_real_get_preferred_height (GtkWidget *widget,
                                                  gint      *minimum_height,
                                                  gint      *natural_height)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->get_preferred_height (widget, minimum_height, natural_height);

  if (window->priv->menubar != NULL)
    {
      gint menubar_min_height, menubar_nat_height;

300
      gtk_widget_get_preferred_height (window->priv->menubar, &menubar_min_height, &menubar_nat_height);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
      *minimum_height += menubar_min_height;
      *natural_height += menubar_nat_height;
    }
}

static void
gtk_application_window_real_get_preferred_height_for_width (GtkWidget *widget,
                                                            gint       width,
                                                            gint      *minimum_height,
                                                            gint      *natural_height)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->get_preferred_height_for_width (widget, width, minimum_height, natural_height);

  if (window->priv->menubar != NULL)
    {
      gint menubar_min_height, menubar_nat_height;

321
      gtk_widget_get_preferred_height_for_width (window->priv->menubar, width, &menubar_min_height, &menubar_nat_height);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
      *minimum_height += menubar_min_height;
      *natural_height += menubar_nat_height;
    }
}

static void
gtk_application_window_real_get_preferred_width (GtkWidget *widget,
                                                 gint      *minimum_width,
                                                 gint      *natural_width)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->get_preferred_width (widget, minimum_width, natural_width);

  if (window->priv->menubar != NULL)
    {
      gint menubar_min_width, menubar_nat_width;

341
      gtk_widget_get_preferred_width (window->priv->menubar, &menubar_min_width, &menubar_nat_width);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
      *minimum_width = MAX (*minimum_width, menubar_min_width);
      *natural_width = MAX (*natural_width, menubar_nat_width);
    }
}

static void
gtk_application_window_real_get_preferred_width_for_height (GtkWidget *widget,
                                                            gint       height,
                                                            gint      *minimum_width,
                                                            gint      *natural_width)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->get_preferred_width_for_height (widget, height, minimum_width, natural_width);

  if (window->priv->menubar != NULL)
    {
      gint menubar_min_width, menubar_nat_width;

362
      gtk_widget_get_preferred_width_for_height (window->priv->menubar, height, &menubar_min_width, &menubar_nat_width);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
      *minimum_width = MAX (*minimum_width, menubar_min_width);
      *natural_width = MAX (*natural_width, menubar_nat_width);
    }
}

static void
gtk_application_window_real_size_allocate (GtkWidget     *widget,
                                           GtkAllocation *allocation)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

  if (window->priv->menubar != NULL)
    {
      GtkAllocation menubar_allocation = *allocation;
      gint menubar_min_height, menubar_nat_height;
      GtkWidget *child;

380
      gtk_widget_get_preferred_height_for_width (window->priv->menubar, allocation->width, &menubar_min_height, &menubar_nat_height);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
381 382

      menubar_allocation.height = menubar_min_height;
383
      gtk_widget_size_allocate (window->priv->menubar, &menubar_allocation);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407

      child = gtk_bin_get_child (GTK_BIN (window));
      if (child != NULL && gtk_widget_get_visible (child))
        {
          GtkAllocation child_allocation = *allocation;
          gint border_width;

          child_allocation.height = MAX (1, child_allocation.height - menubar_min_height);

          border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
          child_allocation.x += border_width;
          child_allocation.y += border_width + menubar_min_height;
          child_allocation.width -= border_width * 2;
          child_allocation.height -= border_width * 2 - menubar_min_height;
          gtk_widget_size_allocate (child, &child_allocation);
        }

      gtk_widget_set_allocation (widget, allocation);
    }
  else
    GTK_WIDGET_CLASS (gtk_application_window_parent_class)
      ->size_allocate (widget, allocation);
}

408 409 410 411
static void
gtk_application_window_real_realize (GtkWidget *widget)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
412
  GtkSettings *settings;
413

414 415 416 417 418 419 420 421 422
  settings = gtk_widget_get_settings (widget);

  g_signal_connect (settings, "notify::gtk-shell-shows-app-menu",
                    G_CALLBACK (gtk_application_window_shell_shows_app_menu_changed), window);
  g_signal_connect (settings, "notify::gtk-shell-shows-menubar",
                    G_CALLBACK (gtk_application_window_shell_shows_menubar_changed), window);

  gtk_application_window_update_shell_shows_app_menu (window, settings);
  gtk_application_window_update_shell_shows_menubar (window, settings);
423
  gtk_application_window_update_menubar (window);
424 425 426 427 428

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->realize (widget);
}

429 430 431 432 433 434 435 436 437 438 439 440 441 442
static void
gtk_application_window_real_unrealize (GtkWidget *widget)
{
  GtkSettings *settings;

  settings = gtk_widget_get_settings (widget);

  g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_app_menu_changed, widget);
  g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_menubar_changed, widget);

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->unrealize (widget);
}

Allison Karlitskaya's avatar
Allison Karlitskaya committed
443 444 445 446 447
static void
gtk_application_window_real_map (GtkWidget *widget)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);

448
  /* XXX could eliminate this by tweaking gtk_window_map */
Allison Karlitskaya's avatar
Allison Karlitskaya committed
449
  if (window->priv->menubar)
450
    gtk_widget_map (window->priv->menubar);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
451 452 453 454 455 456 457 458 459 460 461 462 463 464

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->map (widget);
}

static void
gtk_application_window_real_forall_internal (GtkContainer *container,
                                             gboolean      include_internal,
                                             GtkCallback   callback,
                                             gpointer      user_data)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (container);

  if (window->priv->menubar)
465
    callback (window->priv->menubar, user_data);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
466 467 468 469 470 471 472

  GTK_CONTAINER_CLASS (gtk_application_window_parent_class)
    ->forall (container, include_internal, callback, user_data);
}


static void
473 474 475 476
gtk_application_window_get_property (GObject    *object,
                                     guint       prop_id,
                                     GValue     *value,
                                     GParamSpec *pspec)
Allison Karlitskaya's avatar
Allison Karlitskaya committed
477 478 479 480 481
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);

  switch (prop_id)
    {
482
    case PROP_SHOW_MENUBAR:
483
      g_value_set_boolean (value, window->priv->show_menubar);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
484 485 486 487 488 489 490 491
      break;

    default:
      g_assert_not_reached ();
    }
}

static void
492 493 494 495
gtk_application_window_set_property (GObject      *object,
                                     guint         prop_id,
                                     const GValue *value,
                                     GParamSpec   *pspec)
Allison Karlitskaya's avatar
Allison Karlitskaya committed
496 497 498 499 500
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);

  switch (prop_id)
    {
501 502
    case PROP_SHOW_MENUBAR:
      gtk_application_window_set_show_menubar (window, g_value_get_boolean (value));
Allison Karlitskaya's avatar
Allison Karlitskaya committed
503 504 505 506 507 508 509 510
      break;

    default:
      g_assert_not_reached ();
    }
}

static void
511
gtk_application_window_dispose (GObject *object)
Allison Karlitskaya's avatar
Allison Karlitskaya committed
512 513 514
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (object);

515 516 517 518 519
  if (window->priv->menubar)
    {
      gtk_widget_unparent (window->priv->menubar);
      window->priv->menubar = NULL;
    }
520 521 522

  g_clear_object (&window->priv->app_menu_section);
  g_clear_object (&window->priv->menubar_section);
523
  g_clear_object (&window->priv->actions);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
524 525

  G_OBJECT_CLASS (gtk_application_window_parent_class)
526
    ->dispose (object);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
527 528 529 530 531 532
}

static void
gtk_application_window_init (GtkApplicationWindow *window)
{
  window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, GTK_TYPE_APPLICATION_WINDOW, GtkApplicationWindowPrivate);
533 534

  window->priv->actions = g_simple_action_group_new ();
535 536
  window->priv->app_menu_section = g_menu_new ();
  window->priv->menubar_section = g_menu_new ();
537 538

  /* window->priv->actions is the one and only ref on the group, so when
539
   * we dispose, the action group will die, disconnecting all signals.
540 541 542 543 544 545 546 547 548
   */
  g_signal_connect_swapped (window->priv->actions, "action-added",
                            G_CALLBACK (g_action_group_action_added), window);
  g_signal_connect_swapped (window->priv->actions, "action-enabled-changed",
                            G_CALLBACK (g_action_group_action_enabled_changed), window);
  g_signal_connect_swapped (window->priv->actions, "action-state-changed",
                            G_CALLBACK (g_action_group_action_state_changed), window);
  g_signal_connect_swapped (window->priv->actions, "action-removed",
                            G_CALLBACK (g_action_group_action_removed), window);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
}

static void
gtk_application_window_class_init (GtkApplicationWindowClass *class)
{
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
  GObjectClass *object_class = G_OBJECT_CLASS (class);

  container_class->forall = gtk_application_window_real_forall_internal;
  widget_class->get_preferred_height = gtk_application_window_real_get_preferred_height;
  widget_class->get_preferred_height_for_width = gtk_application_window_real_get_preferred_height_for_width;
  widget_class->get_preferred_width = gtk_application_window_real_get_preferred_width;
  widget_class->get_preferred_width_for_height = gtk_application_window_real_get_preferred_width_for_height;
  widget_class->size_allocate = gtk_application_window_real_size_allocate;
564
  widget_class->realize = gtk_application_window_real_realize;
565
  widget_class->unrealize = gtk_application_window_real_unrealize;
Allison Karlitskaya's avatar
Allison Karlitskaya committed
566 567 568
  widget_class->map = gtk_application_window_real_map;
  object_class->get_property = gtk_application_window_get_property;
  object_class->set_property = gtk_application_window_set_property;
569
  object_class->dispose = gtk_application_window_dispose;
Allison Karlitskaya's avatar
Allison Karlitskaya committed
570

571 572 573 574
  gtk_application_window_properties[PROP_SHOW_MENUBAR] =
    g_param_spec_boolean ("show-menubar",
                          P_("Show a menubar"),
                          P_("TRUE if the application's menus should be included "
Matthias Clasen's avatar
Matthias Clasen committed
575
                             "in the menubar at the top of the window"),
576
                          TRUE, G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
577 578 579 580
  g_object_class_install_properties (object_class, N_PROPS, gtk_application_window_properties);
  g_type_class_add_private (class, sizeof (GtkApplicationWindowPrivate));
}

581 582 583 584 585 586 587 588 589 590
/**
 * gtk_application_window_new:
 * @application: a #GtkApplication
 *
 * Creates a new #GtkApplicationWindow.
 *
 * Returns: a newly created #GtkApplicationWindow
 *
 * Since: 3.4
 */
Allison Karlitskaya's avatar
Allison Karlitskaya committed
591 592 593 594 595 596 597 598 599 600 601
GtkWidget *
gtk_application_window_new (GtkApplication *application)
{
  g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);

  return g_object_new (GTK_TYPE_APPLICATION_WINDOW,
                       "application", application,
                       NULL);
}

gboolean
602
gtk_application_window_get_show_menubar (GtkApplicationWindow *window)
Allison Karlitskaya's avatar
Allison Karlitskaya committed
603
{
604
  return window->priv->show_menubar;
605 606
}

607 608 609
void
gtk_application_window_set_show_menubar (GtkApplicationWindow *window,
                                         gboolean              show_menubar)
610
{
611
  g_return_if_fail (GTK_IS_APPLICATION_WINDOW (window));
612

613
  show_menubar = !!show_menubar;
614

615
  if (window->priv->show_menubar != show_menubar)
616
    {
617 618 619
      window->priv->show_menubar = show_menubar;

      gtk_application_window_update_menubar (window);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
620

621
      g_object_notify_by_pspec (G_OBJECT (window), gtk_application_window_properties[PROP_SHOW_MENUBAR]);
Allison Karlitskaya's avatar
Allison Karlitskaya committed
622 623
    }
}