/!\ This page describes best practices for dialogs in GTK3. With GTK4, some details might be different. /!\

Dialogs

GtkDialog is a very flexible API (really, too flexible), and lets you do many things in multiple ways. This document tries to capture best practices. The Dialogs section of the HIG is a very good source for design questions about dialog.

Constructing Dialogs

GtkDialog and GtkMessageDialog have a number of constructors that allow to specify multiple ingredients in a compact form:

  • transient parent
  • flags, including modality and whether to use a header bar
  • buttons
  • text content (for message dialogs)

Typical usage looks like this

dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
                                 GTK_DIALOG_MODAL|
                                 GTK_DIALOG_DESTROY_WITH_PARENT,
                                 GTK_MESSAGE_INFO,
                                 GTK_BUTTONS_OK,
                                 "The system network services are not compatible with this version.");

or this

dialog = gtk_dialog_new_with_buttons ("Warning",
                                      GTK_WINDOW (parent),
                                      GTK_DIALOG_MODAL|
                                      GTK_DIALOG_DESTROY_WITH_PARENT,
                                      "OK", GTK_RESPONSE_APPLY,
                                      NULL);

Dialogs should always have a transient parent, GTK warns you if you don't do it.

You can also use a GtkBuilder ui file to create a dialog:

<object class="GtkDialog" id="dialog">
  <child type="action">
    <object class="GtkButton" id="cancel">
      <property name="visible">True</property>
      <property name="label">Cancel</property>
    </object>
  </child>
  <child type="action">
    <object class="GtkButton" id="apply">
      <property name="visible">True</property>
      <property name="label">Create Event</property>
      <property name="can-default">True</property>
    </object>
  </child>

...

  <action-widgets>
    <action-widget response="cancel">cancel</action-widget>
    <action-widget response="apply" default="true">apply</action-widget>
  </action-widgets>
</object>

Headerbars

GTK dialogs can use header bars to place buttons and other action widgets at the top instead of the traditional action area at the bottom. The builtin dialogs in GTK adapt to the needs of the desktop they run under by looking at the gtk-dialogs-use-header. Custom dialogs use the action area by default.

To specify that a custom dialog should use a header bar when using a dialog constructor, it is best to use the GTK_DIALOG_USE_HEADER_BAR flag:

dialog = gtk_dialog_new_with_buttons ("Warning",
                                      GTK_WINDOW (parent),
                                      GTK_DIALOG_MODAL|
                                      GTK_DIALOG_USE_HEADER_BAR|
                                      GTK_DIALOG_DESTROY_WITH_PARENT,
                                      "OK", GTK_RESPONSE_APPLY,
                                      NULL);

To specify that a custom dialog should use a header bar when using a dialog constructor, it is best to specify the use-header-bar property for the dialog:

<object class="GtkDialog" id="dialog">
  <property name="use-header-bar">1</property>
  <child type="action">
    <object class="GtkButton" id="cancel">
      <property name="visible">True</property>
      <property name="label">Cancel</property>
    </object>
  </child>
  <child type="action">
    <object class="GtkButton" id="apply">
      <property name="visible">True</property>
      <property name="label">Create Event</property>
      <property name="can-default">True</property>
    </object>
  </child>

...

  <action-widgets>
    <action-widget response="cancel">cancel</action-widget>
    <action-widget response="apply" default="true">apply</action-widget>
  </action-widgets>
</object>

GTK will move buttons (and action widgets) to the header bar that are added in the constructor, and buttons that are added via gtk_dialog_add_button() or gtk_dialog_add_action_widget(), and buttons that are specified as child with type="action" in a ui file. Widgets that are manually added to the action area or header bar (in code or in a ui file) will not be moved, and GTK will ensure that the action area is visible if it contains such children.

Note in particular that children that are added manually in the ui file like this:

<object class="GtkDialog" id="dialog">

...

   <child internal-child="action_area">
     <object class="GtkButtonBox">
        <child>
          <object class="GtkButton" id="cancel">
            <property name="visible">True</property>
            <property name="label">Cancel</property>
          </object>
        </child>
     </object>
   </child>

...

are not relocated. Please use

<object class="GtkDialog" id="dialog">

...

  <child type="action">
    <object class="GtkButton" id="cancel">
      <property name="visible">True</property>
      <property name="label">Cancel</property>
    </object>
  </child>

... 

for creating relocatable action widgets in a ui file.

Adaptive dialogs

GTK builtin dialogs will automatically use a header bar or not, depending on the value of the gtk-dialogs-use-header setting. To achieve the same behavior for custom dialogs, apply the setting yourself like this:

g_object_get (gtk_settings_get_default (), "gtk-dialogs-use-header", &use_header, NULL);

dialog = g_object_new (GTK_TYPE_DIALOG,
                       "transient-for", parent,
                       "use-header-bar", use_header,
                       NULL);

Note that use-header-bar is a construct property, and thus can't be set in a widget template .ui file. Instead you have to specify it when constructing the object, as shown above.