Migrating to Adaptive Dialogs

Migrating to Adaptive Dialogs

Libadwaita 1.5 introduces AdwDialog and replacements for AdwMessageDialog, AdwPreferencesWindow and AdwAboutWindow that derive from it.

While the old widgets are not deprecated yet, they will be in the next release.

Use AdwWindow or AdwApplicationWindow for the Parent Window

To use AdwDialog, your parent window must be an instance of either AdwWindow or AdwApplicationWindow. You should migrate to these widgets if you’re still using GtkWindow or GtkApplicationWindow, respectively.

Stop using window titlebar, instead, create an AdwToolbarView and add the titlebar to it as a top bar. Set the window child as the toolbar view content. Set the toolbar view as the AdwWindow:content property on the window.

If you have GtkSearchBar, GtkActionBar etc in a GtkBox, move them to the toolbar view as well as top/bottom bars respectively.

Example:

<object class="GtkWindow">
  <property name="titlebar">
    <object class="AdwHeaderBar"/>
  </property>
  <property name="child">
    <object class="GtkBox">
      <property name="orientation">vertical</property>
      <child>
        <!-- content -->
      </child>
      <child>
        <object class="GtkActionBar"/>
      </child>
    </object>
  </property>
</object>

becomes this:

<object class="AdwWindow">
  <property name="content">
    <object class="AdwToolbarView">
      <child type="top">
        <object class="AdwHeaderBar"/>
      </child>
      <property name="content">
        <!-- content -->
      </property>
      <child type="bottom">
        <object class="GtkActionBar"/>
      </child>
    </object>
  </property>
</object>

Porting to AdwDialog

The API of AdwDialog is somewhat like a subset of the API of AdwWindow.

GtkWindow AdwDialog
GtkWindow:child AdwDialog:child
GtkWindow:title AdwDialog:title
GtkWindow:default-width AdwDialog:content-width
GtkWindow:default-height AdwDialog:content-height
GtkWindow:resizable AdwDialog:follows-content-size
GtkWindow:focus-widget AdwDialog:focus-widget
GtkWindow:default-widget AdwDialog:default-widget
gtk_window_close() adw_dialog_close()
gtk_window_destroy() adw_dialog_force_close()
gtk_window_present() adw_dialog_present()
AdwWindow AdwDialog
AdwWindow:content AdwDialog:child
AdwWindow:current-breakpoint AdwDialog:current-breakpoint
adw_window_add_breakpoint() adw_dialog_add_breakpoint()

Since these dialogs are within the parent window, they are always destroyed with parent, so there’s no replacement for GtkWindow:destroy-with-parent.

GtkWindow sizing can behave in two ways: when resizable, its size is controlled with GtkWindow:default-width and GtkWindow:default-height. If the content shrinks, the window keeps the size it had before. If the content grows, the window grows with it. When not resizable, it follows the content’s size precisely.

While dialogs are not resizable, they can behave in both ways as well. By default, their size is controlled with AdwDialog:content-width and AdwDialog:content-height, like for resizable windows. Set AdwDialog:follows-content-size to FALSE to follow the content size precisely, like for non-resizable windows.

Since the dialog size is constrained by the parent window, you may want to adjust the content sizes. For example, if it had a small default height just so it doesn’t grow larger than its parent window, that can be increased or removed.

Dialogs are regular widgets, so they can be closed and presented again endlessly as long as you hold a reference to them. If you were setting the GtkWindow:hide-on-close property to TRUE, do that instead.

Dialogs are always modal. The GtkWindow:transient-for property is replaced by a parameter in adw_dialog_present().

Tip

The widget passed into adw_dialog_present() doesn’t have to be a window. You can pass any widget within a window to get the same effect as passing the window itself. This is done both for convenience and to allow for more flexibility in future.

GtkWindow::close-request doesn’t have a direct replacement. When presented as a bottom sheet, dialogs can be swiped down, and because of that you have to specify whether the dialog can be closed right now ahead of time.

  • If you were using ::close-request to completely prevent window closing, set the AdwDialog:can-close property to FALSE.
  • To have a close confirmation, use the AdwDialog::close-attempt signal.
  • adw_dialog_force_close() closes the dialog even when :can-close is set to FALSE, and can be used to close the dialog after the confirmation.
  • If you were using ::close-request just to track when the window is closed, use the AdwDialog::closed signal instead.

Use AdwHeaderBar Instead of GtkHeaderBar

AdwHeaderBar will use the dialog’s title and adjust decoration layout to always include a close button and nothing else. Since GtkHeaderBar doesn’t do this, the dialog will not behave correctly.

Replace your GtkHeaderBar with AdwHeaderBar, and GtkHeaderBar:show-title-buttons with a combination of AdwHeaderBar:show-start-title-buttons and AdwHeaderBar:show-end-title-buttons.

Remove Close Shortcut

AdwDialog can be closed by pressing Esc. If you were handling that manually, you can stop doing it.

Port AdwAboutWindow to AdwAboutDialog

AdwAboutDialog has identical API to AdwAboutWindow, so just replace the function calls as appropriate - for example, adw_about_window_add_link() with adw_about_dialog_add_link() and so on.

Port AdwPreferencesWindow to AdwPreferencesDialog

AdwPreferencesDialog has very similar API to AdwPreferencesWindow, and only needs a few adjustments.

Stop Using Deprecated API

The deprecated subpage API has been removed. Refer to the breakpoints migration guide for information on how to replace it.

Adapt to Search Changes

AdwPreferencesDialog changes the default of the AdwPreferencesWindow:search-enabled property to FALSE.

If you want search, make sure to set it to TRUE manually, and if you were disabling it, you can stop doing so.

Otherwise, replace the function calls as appropriate, for example adw_preferences_window_add_toast() with adw_preferences_dialog_add_toast() and so on.

Port AdwMessageDialog to AdwAlertDialog

AdwAlertDialog has mostly similar API to AdwMessageDialog.

Adapt to Constructor Changes

adw_alert_dialog_new() doesn’t accept a parent window anymore, so remove that parameter. Instead, pass it as a parameter to adw_dialog_present() or adw_alert_dialog_choose().

Adapt to adw_alert_dialog_choose() Changes

Just like adw_dialog_present(), adw_alert_dialog_choose() now takes the parent widget as a parameter.

Tip

The widget passed into adw_alert_dialog_choose() doesn’t have to be a window. You can pass any widget within a window to get the same effect as passing the window itself. This is done both for convenience and to allow for more flexibility in future.

Stop Using adw_message_dialog_response()

adw_message_dialog_response() has no replacement. Most applications shouldn’t be using it in the first place, but if you really do, emit the AdwAlertDialog::response signal manually instead.

Otherwise, replace the function calls as appropriate, for example adw_message_dialog_add_response() with adw_alert_dialog_add_response() and so on.

Adapt to Scrolling

AdwAlertDialog can scroll its content. If you were setting a GtkScrolledWindow as AdwMessageDialog:extra-child, you may want to remove the scrolled window and use its contents directly.