]> Migrating from GTK 3.x to GTK 4 GTK 4 is a major new version of GTK that breaks both API and ABI compared to GTK 3.x. Thankfully, most of the changes are not hard to adapt to and there are a number of steps that you can take to prepare your GTK 3.x application for the switch to GTK 4. After that, there's a small number of adjustments that you may have to do when you actually switch your application to build against GTK 4.
Preparation in GTK 3.x The steps outlined in the following sections assume that your application is working with GTK 3.24, which is the final stable release of GTK 3.x. It includes all the necessary APIs and tools to help you port your application to GTK 4. If you are still using an older version of GTK 3.x, you should first get your application to build and work with the latest minor release in the 3.24 series.
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 GTK 3 also includes an index of all deprecated symbols. To verify that your program does not use any deprecated symbols, you can use defines to remove deprecated symbols from the header files, as follows: make CFLAGS+="-DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED" Note that some parts of our API, such as enumeration values, are not well covered by the deprecation warnings. In most cases, using them will require you to also use deprecated functions, which will trigger warnings.
Enable diagnostic warnings Deprecations of properties and signals cannot be caught at compile time, as both properties and signals are installed and used after types have been instantiated. In order to catch deprecations and changes in the run time components, you should use the G_ENABLE_DIAGNOSTIC environment variable when running your application, e.g.: G_ENABLE_DIAGNOSTIC=1 ./your-app
Do not use widget style properties Style properties do not exist in GTK 4. You should stop using them in your custom CSS and in your code.
Review your window creation flags GTK 4 removes the GDK_WA_CURSOR flag. Instead, just use gdk_window_set_cursor() to set a cursor on the window after creating it. GTK 4 also removes the GDK_WA_VISUAL flag, and always uses an RGBA visual for windows. To prepare your code for this, use gdk_window_set_visual (gdk_screen_get_rgba_visual ()) after creating your window. GTK 4 also removes the GDK_WA_WMCLASS flag. If you need this X11-specific functionality, use XSetClassHint() directly.
Stop using non-RGBA visuals GTK 4 always uses RGBA visuals for its windows; you should make sure that your code works with that. At the same time, you should stop using GdkVisual APIs, this object not longer exist in GTK 4. Most of its APIs are deprecated already and not useful when dealing with RGBA visuals.
Stop using GtkBox:padding, GtkBox:fill and GtkBox:expand GTK4 removes these #GtkBox child properties, so you should not use them. You can replace GtkBox:padding using the #GtkWidget:margin properties on your #GtkBox child widgets. The fill child property can be replaced by setting appropriate values for the #GtkWidget:halign and #GtkWidget:valign properties of the child widgets. If you previously set the fill child property to %TRUE, you can achieve the same effect by setting the halign or valign properties to %GTK_ALIGN_FILL, depending on the parent box -- halign for a horizontal box, valign for a vertical one. #GtkBox also uses the expand child property. It can be replaced by setting #GtkWidget:hexpand or #GtkWidget:vexpand on the child widgets. To match the old behavior of the #GtkBox's expand child property, you need to set #GtkWidget:hexpand on the child widgets of a horizontal #GtkBox and #GtkWidget:vexpand on the child widgets of a vertical #GtkBox. Note that there's a subtle but important difference between #GtkBox's expand and fill child properties and the ones in #GtkWidget: setting #GtkWidget:hexpand or #GtkWidget:vexpand to %TRUE will propagate up the widget hierarchy, so a pixel-perfect port might require you to reset the expansion flags to %FALSE in a parent widget higher up the hierarchy.
Stop using the state argument of GtkStyleContext getters The getters in the GtkStyleContext API, such as gtk_style_context_get_property(), gtk_style_context_get(), or gtk_style_context_get_color() only accept the context's current state for their state argument. You should update all callers to pass the current state.
Stop using gdk_pixbuf_get_from_window() and gdk_cairo_set_source_surface() These functions are not supported in GTK 4. Instead, either use backend-specific APIs, or render your widgets using gtk_widget_render().
Stop using GtkButton's image-related API The functions and properties related to automatically add a GtkImage to a GtkButton, and using a GtkSetting to control its visibility, are not supported in GTK 4. Instead, you can just pack a GtkImage inside a GtkButton, and control its visibility like you would for any other widget. If you only want to add a named icon to a GtkButton, you can use gtk_button_set_icon_name().
Stop using GtkWidget event signals Event controllers and #GtkGestures replace event signals in GTK 4. They have been backported to GTK 3.x so you can prepare for this change.
Set a proper app_id In GTK4 we want the application's #GApplication 'application-id' (and therefore the D-Bus name), the desktop file basename and Wayland's xdg-shell app_id to match. In order to achieve this with GTK3 call g_set_prgname() with the same application id you passed to #GtkApplication. Rename your desktop files to match the application id if needed. The call to g_set_prgname() can be removed once you fully migrated to GTK4.
Stop using GtkBox's pack-type child property In order to improve performance and simplify the widget, GtkBox lost its 'pack-type' child property. In GTK4, every GtkBox instance has a simple list of child widgets that it allocates from start to end. The old behavior of pack-type=END can be emulated by simply making the box child in the center hexpand and right-align the ones at the end.
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 GTK 4. Making it possible to prepare for these in GTK 3 would have been either impossible or impractical.
Stop using GdkScreen The GdkScreen object has been removed in GTK 4. Most of its APIs already had replacements in GTK 3 and were deprecated, a few remaining replacements have been added to GdkDisplay.
Stop using the root window The root window is an X11-centric concept that is no longer exposed in the backend-neutral GDK API. gdk_surface_get_parent() will return %NULL for toplevel windows. If you need to interact with the X11 root window, you can use gdk_x11_display_get_xrootwindow() to get its XID.
Stop using GdkVisual This object is not useful with current GTK drawing APIs and has been removed without replacement.
Stop using GdkDeviceManager The GdkDeviceManager object has been removed in GTK 4. Most of its APIs already had replacements in GTK 3 and were deprecated in favor of GdkSeat.
Adapt to GdkWindow API changes GdkWindow has been renamed to GdkSurface. The gdk_window_new() function has been replaced by a number of more specialized constructors: gdk_surface_new_toplevel(), gdk_surface_new_popup(), gdk_surface_new_temp(), gdk_surface_new_child(), gdk_surface_new_input(), gdk_wayland_surface_new_subsurface(). Use the appropriate ones to create your windows. Native and foreign subwindows are no longer supported. These concepts were complicating the code and could not be supported across backends. gdk_window_reparent() is no longer available.
Stop accessing GdkEvent fields Direct access to GdkEvent structs is no longer possible in GTK 4. Some frequently-used fields already had accessors in GTK 3, and the remaining fields have gained accessors in GTK 4.
Stop using gdk_surface_set_event_compression Event compression is now always enabled. If you need to see the uncoalesced motion history, use gdk_event_get_motion_history().
Adapt to GdkKeymap API changes The way to get a keymap has changed slightly. gdk_keymap_get_for_display() has been renamed to gdk_display_get_keymap().
Stop using GtkEventBox GtkEventBox is no longer needed and has been removed. All widgets receive all events.
Stop using GtkButtonBox GtkButtonBox has been removed. Use a GtkBox instead.
Adapt to GtkButton API changes GtkBox no longer has pack-start and -end. Pack your widgets in the correct order, or reorder them as necessary.
Adapt to GtkHeaderBar API changes The gtk_header_bar_set_show_close_button() function has been renamed to the more accurate name gtk_header_bar_set_show_title_buttons(). The corresponding getter and the property itself have also been renamed.
Adapt to GtkStack API changes The GtkStack child properties have been converted into child meta object. Instead of gtk_container_child_set (stack, child, …), you can now use g_object_set (gtk_stack_get_page (stack, child), …). In .ui files, the GtkStackPage objects must be created explicitly, and take the child widget as property. gtk4-builder-tool can help with this conversion.
Adapt to GtkStyleContext API changes The getters in the GtkStyleContext API, such as gtk_style_context_get_property(), gtk_style_context_get(), or gtk_style_context_get_color() have lost their state argument, and always use the context's current state. Update all callers to omit the state argument.
Adapt to GtkCssProvider API changes In GTK 4, the various #GtkCssProvider load functions have lost their #GError argument. If you want to handle CSS loading errors, use the #GtkCssProvider::parsing-error signal instead.
Stop using GtkContainer::border-width GTK 4 has removed the #GtkContainer::border-width property. Use other means to influence the spacing of your containers, such as the CSS margin and padding properties on child widgets.
Adapt to GtkWidget's size request changes GTK 3 used five different virtual functions in GtkWidget to implement size requisition, namely the gtk_widget_get_preferred_width() family of functions. To simplify widget implementations, GTK4 uses only one virtual function, GtkWidgetClass::measure() that widgets have to implement.
Adapt to GtkWidget's size allocation changes The #GtkWidget::size-allocate signal now takes the baseline as an argument, so you no longer need to call gtk_widget_get_allocated_baseline() to get it.
Switch to GtkWidget's children APIs Instead of the GtkContainer subclass, in GTK 4, any widget can have children, and there is new API to navigate the widget tree: gtk_widget_get_first_child(), gtk_widget_get_last_child(), gtk_widget_get_next_sibling(), gtk_widget_get_prev_sibling(). The GtkContainer API still works, but if you are implementing your own widgets, you should consider using the new APIs.
Don't use -gtk-gradient in your CSS GTK now supports standard CSS syntax for both linear and radial gradients, just use those.
Don't use -gtk-icon-effect in your CSS GTK now supports a more versatile -gtk-icon-filter instead. Replace -gtk-icon-effect: dim; with -gtk-icon-filter: opacity(0.5); and -gtk-icon-effect: hilight; with -gtk-icon-filter: brightness(1.2);.
Use gtk_widget_measure gtk_widget_measure() replaces the various gtk_widget_get_preferred_ functions for querying sizes.
Adapt to drawing model changes This area has seen the most radical changes in the transition from GTK 3 to GTK 4. Widgets no longer use a draw() function to render their contents to a cairo surface. Instead, they have a snapshot() function that creates one or more GskRenderNodes to represent their content. Third-party widgets that use a draw() function or a #GtkWidget::draw signal handler for custom drawing will need to be converted to use gtk_snapshot_append_cairo(). The auxiliary #GtkSnapshot object has APIs to help with creating render nodes. If you are using a #GtkDrawingArea for custom drawing, you need to switch to using gtk_drawing_area_set_draw_func() to set a draw function instead of connnecting a handler to the #GtkWidget::draw signal.
Stop using APIs to query GdkSurfaces A number of APIs for querying special-purpose windows have been removed, since these windows are no longer publically available: gtk_tree_view_get_bin_window(), gtk_viewport_get_bin_window(), gtk_viewport_get_view_window().
Widgets are now visible by default The default value of #GtkWidget::visible in GTK 4 is %TRUE, so you no longer need to explicitly show all your widgets. On the flip side, you need to hide widgets that are not meant to be visible from the start. A convenient way to remove unnecessary property assignments like this from ui files it run the command gtk4-builder-tool simplify --replace on them. The function gtk_widget_show_all(), the #GtkWidget::no-show-all property and its getter and setter have been removed in GTK 4, so you should stop using them.
Adapt to changes in animated hiding and showing of widgets Widgets that appear and disappear with an animation, such as GtkPopover, GtkInfoBar, GtkRevealer no longer use gtk_widget_show() and gtk_widget_hide() for this, but have gained dedicated APIs for this purpose that you should use.
Stop passing commandline arguments to gtk_init The gtk_init() and gtk_init_check() functions no longer accept commandline arguments. Just call them without arguments. Other initialization functions that were purely related to commandline argument handling, such as gtk_parse_args() and gtk_get_option_group(), are gone. The APIs to initialize GDK separately are also gone, but it is very unlikely that you are affected by that.
GdkPixbuf is deemphasized A number of #GdkPixbuf-based APIs have been removed. The available replacements are either using #GIcon, or the newly introduced #GdkTexture or #GdkPaintable classes instead. If you are dealing with pixbufs, you can use gdk_texture_new_for_pixbuf() to convert them to texture objects where needed.
GtkWidget event signals are removed Event controllers and #GtkGestures have already been introduced in GTK 3 to handle input for many cases. In GTK 4, the traditional widget signals for handling input, such as #GtkWidget::motion-event or #GtkWidget::event have been removed.
Invalidation handling has changed Only gtk_widget_queue_draw() is left to mark a widget as needing redraw. Variations like gtk_widget_queue_draw_rectangle() or gtk_widget_queue_draw_region() are no longer available.
Stop using GtkWidget::draw The #GtkWidget::draw signal has been removed. Widgets need to implement the #GtkWidget::snapshot function now. Connecting draw signal handlers is no longer possible.
Window content observation has changed Observing widget contents and widget size is now done by using the #GtkWidgetPaintable object instead of connecting to widget signals.
The gtk_window_fullscreen_on_monitor API has changed Instead of a monitor number, gtk_window_fullscreen_on_monitor() now takes a #GdkMonitor argument.
Adapt to cursor API changes Use the new gtk_widget_set_cursor() function to set cursors, instead of setting the cursor on the underlying window directly. This is necessary because most widgets don't have their own window anymore, turning any such calls into global cursor changes. For creating standard cursors, gdk_cursor_new_for_display() has been removed, you have to use cursor names instead of GdkCursorType. For creating custom cursors, use gdk_cursor_new_from_texture(). The ability to get cursor images has been removed.
Adapt to icon size API changes Instead of the existing extensible set of symbolic icon sizes, GTK now only supports normal and large icons with the #GtkIconSize enumeration. The actual sizes can be defined by themes via the CSS property -gtk-icon-size. GtkImage setters like gtk_image_set_from_icon_name() no longer take a #GtkIconSize argument. You can use the separate gtk_image_set_icon_size() setter if you need to override the icon size. The ::stock-size property of GtkCellRendererPixbuf has been renamed to #GtkCellRendererPixbuf:icon-size.
Convert .ui files The simplify command of gtk4-builder-tool has gained a --3to4 option, which can help with some of the required changes in .ui files, such as converting child properties to child meta objects.