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.

Larger changes

Some of the larger themes of GTK 4 development are hard to cover in the form of checklist items, so we mention them separately up-front.

Subclassing

Compared to previous versions, GTK 4 emphasizes composition and delegation over subclassing. As a consequence, many widgets can no longer be subclassed. In most cases, you should look deriving your widget directly from GtkWidget and use complex widgets as child widgets instead of deriving from them.

Life-cycle handling

Widgets in GTK 4 are treated like any other objects - their parent widget holds a reference on them, and GTK holds a reference on toplevel windows. gtk_window_destroy() will drop the reference on the toplevel window, and cause the whole widget hierarchy to be finalized unless there are other references that keep widgets alive.

The “destroy” signal is emitted when a widget is disposed, and therefore can no longer be used to break reference cycles. A typical sign of a reference cycle involving a toplevel window is when closing the window does not make the application quit.

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. 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.

In GTK 4, the two roles of a standalone toplevel window and of a popup that is placed relative to a parent window have been separated out into two interfaces, GdkToplevel and GdkPopup. Surfaces implementing these interfaces are created with gdk_surface_new_toplevel() and gdk_surface_new_popup(), respectively, and they are presented on screen using gdk_toplevel_present() and gdk_popup_present(). The present() functions take parameters in the form of an auxiliary layout struct, GdkPopupLayout or GdkToplevelLayout. If your code is dealing directly with surfaces, you may have to change it to call the API in these interfaces, depending on whether the surface you are dealing with is a toplevel or a popup.

As part of this reorganization, X11-only concepts such as sticky, keep-below, urgency, skip-taskbar or window groups have either been removed or moved to X11 backend api. If you need to use them on your X11 windows, you will have to use those backend apis or set the corresponding X11 properties (as specified in the EWMH) yourself.

Subsurfaces are only supported with the Wayland backend, using gdk_wayland_surface_new_subsurface(). Native and foreign subwindows are no longer supported. These concepts were complicating the code and could not be supported across backends.

A number of GdkWindow APIs are no longer available. This includes gdk_window_reparent(), gdk_window_set_geometry_hints(), gdk_window_raise(), gdk_window_restack(), gdk_window_move(), gdk_window_resize(). If you need to manually control the position or stacking of your X11 windows, you you will have to use Xlib apis.

A number of minor API cleanups have happened in GdkSurface as well. For example, gdk_surface_input_shape_combine_region() has been renamed to gdk_surface_set_input_region(), and gdk_surface_begin_resize_drag() has been renamed to gdk_toplevel_begin_resize().

The iconified window state has been renamed to minimized

The GDK_TOPLEVEL_STATE_ICONIFIED value of the GdkSurfaceState enumeration is now GDK_TOPLEVEL_STATE_MINIMIZED in the GdkToplevelState enumeration.

The GdkWindow functions gdk_window_iconify() and gdk_window_deiconify() have been renamed to gdk_toplevel_minimize() and gdk_toplevel_present(), respectively.

The behavior of the minimization and unminimization operations have not been changed, and they still require support from the underlying windowing system.

Adapt to GdkEvent API changes

Direct access to GdkEvent structs is no longer possible in GTK 4. GdkEvent is now a strictly read-only type, and you can no longer change any of its fields, or construct new events. All event fields have accessors that you will have to use.

Event compression is always enabled in GTK 4, for both motion and scroll events. If you need to see the uncoalesced motion or scroll history, use gdk_event_get_history() on the latest event.

Stop using grabs

GTK 4 no longer provides the gdk_device_grab() or gdk_seat_grab() apis. If you need to dismiss a popup when the user clicks outside (the most common use for grabs), you can use the GdkPopup “autohide” property instead. GtkPopover also has a “autohide” property for this. If you need to prevent the user from interacting with a window while a dialog is open, use the “modal” property of the dialog.

Adapt to coordinate API changes

A number of coordinate APIs in GTK 3 had _double variants: gdk_device_get_surface_at_position(), gdk_surface_get_device_position(). These have been changed to use doubles, and the _double variants have been removed. Update your code accordingly.

Any APIs that deal with global (or root) coordinates have been removed in GTK 4, since not all backends support them. You should replace your use of such APIs with surface-relative equivalents. Examples of this are gdk_surface_get_origin(), gdk_surface_move() or gdk_event_get_root_coords().

Adapt to GdkKeymap API changes

GdkKeymap no longer exists as an independent object.

If you need access to keymap state, it is now exposed as properties on the GdkDevice representing the keyboard: “direction”, “has-bidi-layouts”, “caps-lock-state”, “num-lock-state”, “scroll-lock-state” and “modifier-state”. To obtain the keyboard device, you can use gdk_seat_get_keyboard (gdk_display_get_default_seat (display).

If you need access to translated keys for event handling, GdkEvent now includes all of the translated key state, including consumed modifiers, group and shift level, so there should be no need to manually call gdk_keymap_translate_keyboard_state() (which has been removed).

If you need to do forward or backward mapping between key codes and key values, use gdk_display_map_keycode() and gdk_display_map_keyval(), which are the replacements for gdk_keymap_get_entries_for_keycode() and gdk_keymap_get_entries_for_keyval().

Adapt to changes in keyboard modifier handling

GTK 3 has the idea that use of modifiers may differ between different platforms, and has a GdkModifierIntent api to let platforms provide hint about how modifiers are expected to be used. It also promoted the use of <Primary> instead of <Control> to specify accelerators that adapt to platform conventions.

In GTK 4, the meaning of modifiers has been fixed, and backends are expected to map the platform conventions to the existing modifiers. The expected use of modifiers in GTK 4 is:

GDK_CONTROL_MASK

Primary accelerators

GDK_ALT_MASK

Mnemonics

GDK_SHIFT_MASK

Extending selections

GDK_CONTROL_MASK

Modifying selections

GDK_CONTROL_MASK|GDK_ALT_MASK

Prevent text input

Consequently, GdkModifierIntent and related APIs have been removed, and <Control> is preferred over <Primary> in accelerators.

A related change is that GTK 4 no longer supports the use of archaic X11 real modifiers with the names Mod1,…, Mod5, and GDK_MOD1_MASK has been renamed to GDK_ALT_MASK.

Replace GtkClipboard with GdkClipboard

The GtkClipboard API has been removed, and replaced by GdkClipboard. There is not direct 1:1 mapping between the old an the new API, so it cannot be a mechanical replacement; the new API is based on object types and GValue like object properties, instead of opaque identifiers, so it should be easier to use.

For instance, the example below copies the contents of an entry into the clipboard:

static void
copy_text (GtkWidget *widget)
{
  GtkEditable *editable = GTK_EDITABLE (widget);

  // Initialize a GValue with the contents of the widget
  GValue value = G_VALUE_INIT;
  g_value_init (&value, G_TYPE_STRING);
  g_value_set_string (&value, gtk_editable_get_text (editable));

  // Store the value in the clipboard object
  GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
  gdk_clipboard_set_value (clipboard, &value);

  g_value_unset (&value);
}

whereas the example below pastes the contents into the entry:

static void
paste_text (GtkWidget *widget)
{
  GtkEditable *editable = GTK_EDITABLE (widget);

  // Initialize a GValue to receive text
  GValue value = G_VALUE_INIT;
  g_value_init (&value, G_TYPE_STRING);

  // Get the content provider for the clipboard, and ask it for text
  GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
  GdkContentProvider *provider = gdk_clipboard_get_content (clipboard);

  // If the content provider does not contain text, we are not interested
  if (!gdk_content_provider_get_value (provider, &value, NULL))
    return;

  const char *str = g_value_get_string (&value);

  gtk_editable_set_text (editable, str);

  g_value_unset (&value);
}

The convenience API for specific target types in GtkClipboard has been replaced by their corresponding GType:

GtkClipboard GType
gtk_clipboard_request_text() G_TYPE_STRING
gtk_clipboard_request_rich_text() GTK_TYPE_TEXT_BUFFER
gtk_clipboard_request_image() GDK_TYPE_PIXBUF
gtk_clipboard_request_uris() GDK_TYPE_FILE_LIST

Note: Support for rich text serialization across different processes for GtkTextBuffer is not available any more.

If you are copying the contents of an image, it is recommended to use GDK_TYPE_PAINTABLE instead of GDK_TYPE_PIXBUF, to minimize the amount of potential copies.

Stop using gtk_get_current_... APIs

The function gtk_get_current_event() and its variants have been replaced by equivalent event controller APIs: gtk_event_controller_get_current_event(), etc.

Convert your ui files

A number of the changes outlined below affect .ui files. The gtk4-builder-tool simplify command can perform many of the necessary changes automatically, when called with the –3to4 option. You should always review the resulting changes.

The <requires> tag now supports for the lib attribute the gtk value only, instead of the gtk+ one previously.