Migrating from Libhandy 1.4 to Libadwaita
Libadwaita is being developed as a successor to Libhandy 1.4. As such, it offers to GTK 4 many features Libhandy was offering to GTK 3.
Migrating from Libhandy 1.4 to Libadwaita implies migrating from GTK 3 to 4. This guide only focuses on on Libhandy and Libadwaita, and is designed to be used together with the GTK 3 to 4 migration guide.
If you notice that some differences between Libhandy and Libadwaita are missing in this guide, please report them.
Preparation in Libhandy 1.4
The steps outlined in the following sections assume that your software is working with Libhandy 1.4, which is the latest stable release of Libhandy 1.x. It includes all the necessary APIs and tools to help you port your software to Libadwaita. If you are using an older version of Libhandy, you should first get your software to build and work with Libhandy 1.4.
Do not Use Deprecated Symbols
Over the years, a number of functions, and in some cases, entire widgets have been deprecated. These deprecations are clearly spelled out in the API reference, with hints about the recommended replacements. The API reference for Libhandy 1.4 also includes an index of all deprecated symbols.
Following GTK4’s emphasis on composition and delegation over subclassing,
AdwHeaderBar are no longer derivable. As a replacement,
you can subclass
GtkBox and include a leaflet or a header
bar as a child widget.
HdyKeypad has been removed from Libadwaita. Applications that had used it can
copy it in tree instead.
Stop Using Named WM Colors
The following named colors have been removed from the stylesheet in Libadwaita:
Applications should not use them.
HdyFlap Properties for Adding Children Instead of
HdyFlap provides the
separator properties that can be
used for managing children instead of
GtkContainer API. In Libadwaita
the only way to manage
HdyValueObject with non-string values
HdyValueObject has been removed. While it’s not practical to replace the cases
where it’s storing strings in GTK3, as the preferred replacement only exists in
4, it can also be used with any other
GValue. That use has no
replacement and you can instead create your own objects to store those values.
HdyStyleManager Instead of
If your application is setting
TRUE to request dark appearance, consider setting
HDY_COLOR_SCHEME_PREFER_DARK and making sure the application can work with
light appearance as well. If that’s not possible, set it to
If your application is using light appearance, consider setting the color scheme
HDY_COLOR_SCHEME_PREFER_LIGHT and support dark appearance.
In libadwaita color schemes will be the only way to request dark appearance.
Changes that Need to Be Done at the Time of the Switch
This section outlines porting tasks that you need to tackle when you get to the point that you actually build your application against Libadwaita 1. Making it possible to prepare for these in GTK 3 would have been either impossible or impractical.
Same as GTK itself, all widgets that have children have a new API to replace
The following widgets that formerly subclassed
GtkBin have a
child property now:
AdwApplicationWindow have a
content property instead.
For other widgets use the following replacements:
Adding children in a UI file still works.
HdySearchBar has been removed, use
HdyWindowHandle has been removed, use
AdwExpanderRow API Changes
use-underline property and its accessors have been removed. Use
AdwPreferencesRow:use-underline and its accessors instead.
The title and subtitle have markup enabled, make sure to escape it with
g_markup_escape_text() if this is unwanted.
AdwClamp API Changes
HdyClamp previously had
.large style classes
depending on the current size of its child. These style classes are now
added to the child instead of the clamp itself.
AdwComboRow API Changes
AdwComboRow API has been completely overhauled compared to
and closely mirrors
GtkDropDown. Refer to
documentation for details.
hdy_combo_row_bind_name_model() can be replaced with using the
AdwComboRow:model property in conjunction with
hdy_combo_row_bind_model() can be replaced with using the
AdwComboRow:model property in conjunction with
hdy_combo_row_set_for_enum() can be replaced with an
in conjunction with the
AdwComboRow:expression property, for example:
expr = gtk_property_expression_new (ADW_TYPE_ENUM_LIST_ITEM, NULL, "nick"); model = G_LIST_MODEL (adw_enum_list_model_new (GTK_TYPE_ORIENTATION)); adw_combo_row_set_expression (row, expr); adw_combo_row_set_model (row, model);
GtkDropDown, if the model is a
model items can be converted into human-readable strings automatically without
requiring an expression.
HdyComboRow:selected-index property has been renamed to
AdwComboRow:selected and its type changed from
AdwPreferencesGroup API Changes
HdyPreferencesGroup:use-markup has been removed, the labels always use markup now.
HdyEnumValueObject API Changes
HdyEnumValueObject has been renamed to
AdwEnumListItem and can no longer
be manually created. It’s only intended to be used with
HdyValueObject has been removed. The typical use for storing strings in
GListStore can be replaced by using
AdwHeaderBar API Changes
AdwHeaderBar API mostly mirrors
GtkHeaderBar, refer to the
GTK 3 to 4 migration guide
GtkHeaderBar:show-title-buttons property has been split into
AdwHeaderBar:show-end-title-buttons to simplify creating multi-pane
layouts. The corresponding getter and the setter have been split as well.
AdwWindowTitle widget may be useful for replacing the title and subtitle.
HdyHeaderGroup has been removed. Its behavior can be replicated by changing
AdwHeaderBar:show-end-title-buttons properties depending on the layout,
for example binding them to the
AdwLeaflet:folded property as follows:
<object class="AdwLeaflet" id="leaflet"> <child> <object class="GtkBox"> <property name="orientation">vertical</property> <object class="AdwHeaderBar"> <binding name="show-end-title-buttons"> <lookup name="folded">leaflet</lookup> </binding> </object> ... </object> </child> ... <child> <object class="GtkBox"> <property name="orientation">vertical</property> <object class="AdwHeaderBar"> <binding name="show-start-title-buttons"> <lookup name="folded">leaflet</lookup> </binding> </object> ... </object> </child> </object>
HdyDeck has been removed. Instead, an
AdwLeaflet can be used the same way
by setting the
AdwLeaflet:can-unfold property to
AdwSqueezer API Changes
The child properties of
HdySqueezer have been converted into
page objects, similarly to
GtkStack. For example,
adw_squeezer_page_set_enabled() should be used to replace
can-swipe-forward properties have been renamed to
AdwLeaflet:can-navigate-forward, along with their accessors. The new
properties also handle keyboard and mouse shortcuts in addition to swipes.
vhomogeneous-unfolded properties have been replaced by a single
AdwLeaflet:homogeneous property, set to
TRUE by default, applied when
the leaflet is folded for the opposite orientation.
When unfolded, children are never homogeneous. Use
to make them homogeneous if needed.
interpolate-size property has been removed with no replacement, it’s
always enabled when
AdwLeaflet:homogeneous is set to
AdwLeaflet now uses spring animations instead of timed animations for child
transitions. As such, the
child-transition-duration property has been replaced
AdwLeaflet:child-transition-params, allowing to customize the
animation. Unlike the duration, spring parameters are also used for animation
triggered by swipe gestures.
AdwFlap API Changes
AdwFlap now uses spring animations instead of timed animations for reveal
animations. As such, the
reveal-duration property has been replaced with
AdwFlap:reveal-params, allowing to customize the animation. Unlike
the duration, spring parameters are also used for transitions triggered by swipe gestures.
AdwCarousel API changes
AdwCarousel now uses spring animations instead of timed animations for
scrolling. As such, the
animation-duration property has been replaced with
AdwCarousel:scroll-params, allowing to customize the animation. Unlike
the duration, spring parameters are also used for animation triggered by swipe gestures.
adw_carousel_scroll_to_full() method has been removed. Instead,
adw_carousel_scroll_to() has got an additional parameter
Adapt to View Switcher API Changes
AdwViewStack instead of
You should stop using
GtkStack:interpolate-size properties before switching to
auto view switcher policy has been removed.
AdwViewSwitcher only has
narrow and wide policies; if you had used the
auto policy, use an
AdwSqueezer with two view switchers inside.
AdwViewSwitcher API Changes
narrow-ellipsize property has been removed. Narrow view switchers always
ellipsize their labels, wide switchers never do.
AdwViewSwitcherBar API Changes
policy property has been removed. If you had used it, use a plain
AdwViewSwitcher in a
AdwViewSwitcherTitle API Changes
policy property has been removed, the behavior is similar to the removed
auto policy. If you had used
narrow policies, use an
AdwSqueezer with an
AdwViewSwitcher and an
with the switcher having the desired policy.
AdwAvatar API Changes
HdyAvatar:loadable-icon property has been removed along with its getter
and setter. It can be replaced by
functions have been removed, use the newly added
GIcon, so it should just work
for that case.
adw_avatar_draw_to_texture() does not have the
size parameter. Instead, it
uses the avatar’s current size, with no replacement.
AdwStyleManager API Changes
When used with the default style manager,
ADW_COLOR_SCHEME_DEFAULT is now
ADW_COLOR_SCHEME_PREFER_LIGHT instead of
HDY_COLOR_SCHEME_FORCE_LIGHT, following the system dark style preference by
default. Make sure your application works with it, or otherwise set the
ADW_COLOR_SCHEME_FORCE_LIGHT color scheme manually.
AdwSwipeTracker API Changes
AdwSwipeTracker::begin-swipe signal is now emitted immediately before
the swipe starts, after the drag threshold has been reached, and it has lost its
direction parameter. The new
AdwSwipeTracker::prepare signal behaves
begin-swipe did, and can be used instead of it.
The type of the
duration parameter in
AdwTabView API Changes
HdyTabView:shortcut-widget property has been removed with no replacement;
AdwTabView automatically installs shortcuts with the
GTK_SHORTCUT_SCOPE_MANAGED scope, so they are automatically available
throughout the window without the need to set shortcut widget.
If some of these shortcuts conflict with another widget, the latter has priority, and it should work automatically if the widget correctly stops event propagation.
AdwPreferencesWindow API Changes
can-swipe-back property have been renamed to
AdwPreferencesWindow:can-navigate-back, along with its accessors. The
new properties also handle keyboard and mouse shortcuts in addition to swipes.
Adapt to Miscellaneous Changes
hdy_ease_out_cubic() function has been removed. Instead,
adw_easing_ease() can be used with the
Adapt to Stylesheet Changes
If you were using
as a text color, use
@accent_color instead to
make sure the text is readable. You can also use the
.accent style class to apply the correct color.
Stop Using the
.sidebar Style Class
.sidebar style class is now deprecated,
although still works for compatibility reasons. The main use case - adjusting
the background color of
GtkListView - can now
be done with the
class on those widgets instead, along with adjusting the item selection style.
The border can be replicated by manually adding a
Adapt to the
popover.combo Style Removal
.combo popover style class has been removed. Use
.menu instead. You may need to remove
manually added margins, padding or minimum height from the list items inside
while doing it.
Adapt to the
button.list-button Style Removal
.list-button style class has been removed with no replacement. The regular
button style should be used instead.
Adapt to the
content-view Style Removal
.content-view style class has been removed. The selection mode
GtkCheckButton style had inside content views has been split out into a
separate style class
.selection-mode that can be
applied directly onto check buttons instead of the view. The unique background
color has no replacement and the default background should be used instead.
Adapt to Header Bar, Action Bar, Search Bar and Toolbar Style Changes
When possible, buttons in
GtkSearchBar will use flat appearance by default.
The following rules are used when deciding when to make buttons flat or not:
The following buttons get flat appearance:
- Icon-only buttons;
- Buttons with an icon and a label (using
- Menu buttons containing an arrow;
- Any other button with the
The following buttons keep default appearance:
- Text-only buttons;
- Buttons with other content;
- Buttons within widgets containing the
- Buttons with the
- Buttons with the
It’s important to avoid ambiguous layouts, for example text-only buttons with no icon, since such a button would be indistinguishable from the window title without hovering it.
In rare cases, the existing layout may need a redesign to work with the new style.
The same rules are also used for the
style class now, instead of making every button appear flat.
Adapt to List Style Changes
For boxed lists we now have the
.boxed-list style class that matches
the name of the design pattern. If you were using the
.content style class, you should use
.content style class currently remains for compatibility purposes.
.content style class nor the
.boxed-list style class work
GtkListView, as the widget cannot currently be used for the
boxed list pattern.
If you’re bundling icons from the icon library with your application, make sure to update them. Many icons have been redrawn to be larger to work better without button frames.
If you’re using the
object-select-symbolic icon in a header bar button
(typically for selection mode), use
Adjusting Icon+Arrow Menu Buttons
If you had menu buttons containing an icon and a dropdown arrow, switch to
GtkMenuButton:icon-name and set the
GtkMenuButton:always-show-arrow property to
Adjusting Text-only Buttons
If you had text-only buttons, consider using
AdwButtonContent. For example,
the following button:
<object class="GtkButton"> <property name="label" translatable="yes">_Open</property> <property name="use-underline">True</property> </object>
can be changed into:
<object class="GtkButton"> <property name="child"> <object class="AdwButtonContent"> <property name="icon-name">document-open-symbolic</property> <property name="label" translatable="yes">_Open</property> <property name="use-underline">True</property> </object> </property> </object>
One exception are the two primary buttons in a dialog, for example, “Cancel” and “Open”. Those buttons should retain their default appearance.
Adjusting Split Buttons
If you had split buttons implemented via a
GtkBox with the
.linked style class and two buttons
packed inside, use
AdwSplitButton as follows:
<object class="AdwSplitButton"> <property name="menu-model">some_menu</property> <property name="icon-name">view-list-symbolic</property> </object>
Adjusting Linked Buttons
For other linked together buttons, simply stop linking them.
If multiple linked groups were used to separate different groups of actions, insert extra spacing as follows:
<object class="GtkSeparator"> <style> <class name="spacer"/> </style> </object>
.raised style classes can always be used to
override the default appearance.
GtkButton:has-frame property will not be set to
FALSE when a button gets the flat appearance automatically. It also cannot be
TRUE to make a button raised, the style class should be used directly instead.