![]() |
![]() |
![]() |
![]() |
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.
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.
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.
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.
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.
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.
This object is not useful with current GTK drawing APIs and has been removed without replacement.
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.
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 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.
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.
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.
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()
.
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()
.
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
.
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 |
---|---|
|
G_TYPE_STRING
|
|
GTK_TYPE_TEXT_BUFFER
|
|
GDK_TYPE_PIXBUF
|
|
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.
The function gtk_get_current_event()
and its variants have been
replaced by equivalent event controller APIs:
gtk_event_controller_get_current_event()
, etc.
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.
gtk_builder_connect_signals()
no longer exists. Instead, signals
are always connected automatically. If you need to add user data
to your signals, gtk_builder_set_current_object()
must be
called. An important caveat is that you have to do this before
loading any XML. This means if you need to use
gtk_builder_set_current_object()
, you can no longer use
gtk_builder_new_from_file()
, gtk_builder_new_from_resource()
, or
gtk_builder_new_from_string()
. Instead, you must use vanilla
gtk_builder_new()
, then call gtk_builder_set_current_object()
,
then load the XML using gtk_builder_add_from_file()
,
gtk_builder_add_from_resource()
, or
gtk_builder_add_from_string()
. You must check the return value
for failure and manually abort with g_error()
if something went
wrong.
You only have to worry about this if you were previously using
gtk_builder_connect_signals()
. If you are using templates, then
gtk_widget_init_template()
will call
gtk_builder_set_current_object()
for you, so templates work like
before.
A few changes to the event controller and GtkGesture APIs did not make it back to GTK 3, and have to be taken into account when moving to GTK 4. One is that the “enter” and “leave” signals have gained new arguments. Another is that GtkGestureMultiPress has been renamed to GtkGestureClick, and has lost its area property. A GtkEventControllerFocus has been split off from GtkEventcontrollerKey.
In GTK 3, “widget” was a construct-only
property, so a GtkWidget was provided whenever constructing a
GtkEventController. In GTK 4, “widget” is now
read-only. Use gtk_widget_add_controller()
to add an event
controller to a widget.
In GTK 3, widgets did not own their event controllers, and event
controllers did not own their widgets, so developers were
responsible for manually keeping event controllers alive for the
lifetime of their associated widgets. In GTK 4, widgets own
their event controllers. gtk_widget_add_controller()
takes
ownership of the event controller, so there is no longer any
need to store a reference to the event controller after it has
been added to a widget.
Although not normally needed, an event controller could be
removed from a widget in GTK 3 by destroying the event
controller with g_object_unref()
. In GTK 4, you must use
gtk_widget_remove_controller()
.
The semantics of the “can-focus” property have changed.
In GTK 3, this property only meant that the widget itself would
not accept keyboard input, but its children still might (in the
case of containers). In GTK 4, if :can-focus is FALSE
, the
focus cannot enter the widget or any of its descendents, and the
default value has changed from FALSE
to TRUE
. In addition,
there is a “focusable” property, which controls whether
an individual widget can receive the input focus.
The feature to automatically keep the focus widget scrolled into
view with gtk_container_set_focus_vadjustment()
has been removed
together with GtkContainer, and is provided by scrollable
widgets instead. In the common case that the scrollable is a
GtkViewport, use “scroll-to-focus”.
The APIs for keyboard shortcuts and accelerators have changed in GTK 4.
Instead of GtkAccelGroup, you now use a GtkShortcutController
with global scope, and instead of GtkBindingSet, you now use
gtk_widget_class_add_shortcut()
, gtk_widget_class_add_binding()
and its variants. In both cases, you probably want to add
actions that can be triggered by your shortcuts.
There is no direct replacement for loading and saving accelerators with GtkAccelMap. But since GtkShortcutController implements GListModel and both GtkShortcutTrigger and GtkShortcutAction can be serialized to strings, it is relatively easy to implement saving and loading yourself.
GtkEventBox is no longer needed and has been removed. All widgets receive all events.
The GtkBox pack-start and -end methods have been replaced by
gtk_box_prepend()
and gtk_box_append()
. You can also reorder box
children as necessary.
Following the GdkSurface changes, a number of GtkWindow APIs
that were X11-specific have been removed. This includes
gtk_window_set_geometry_hints()
, gtk_window_set_gravity()
,
gtk_window_move()
, gtk_window_parse_geometry()
,
gtk_window_set_keep_above()
, gtk_window_set_keep_below()
,
gtk_window_begin_resize_drag()
, gtk_window_begin_move_drag()
.
Most likely, you should just stop using them. In some cases, you
can fall back to using the underlying GdkToplevel APIs (for
example, gdk_toplevel_begin_resize()
).
The APIs for controlling GtkWindow size have changed to be
better aligned with the way size changes are integrated in the
frame cycle. gtk_window_resize()
and gtk_window_get_size()
have
been removed. Instead, use gtk_window_set_default_size()
and
gtk_window_get_default_size()
.
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. The
default value of the property is now TRUE
instead of FALSE
.
The gtk_header_bar_set_custom_title()
function has been renamed
to the more accurate name gtk_header_bar_set_title_widget()
. The
corresponding getter and the property itself have also been
renamed.
The gtk_header_bar_set_title()
function has been removed along
with its corresponding getter and the property. By default
GtkHeaderBar shows the title of the window, so if you were
setting the title of the header bar, consider setting the window
title instead. If you need to show a title that’s different from
the window title, use the “title-widget” property to
add a GtkLabel as shown in the example in the GtkHeaderBar
documentation.
The gtk_header_bar_set_subtitle()
function has been removed
along with its corresponding getter and the property. The old
“subtitle” behavior can be replicated by setting
the “title-widget” property to a GtkBox with two
labels inside, with the title label matching the example in
GtkHeaderBar documentation, and the subtitle label being
similar, but with “subtitle” style class instead of
“title”.
The gtk_header_bar_set_has_subtitle()
function has been removed
along with its corresponding getter and the property. Its
behavior can be replicated by setting the
“title-widget” property to a GtkStack with
“vhomogeneous” property set to TRUE
and two pages, each
with a GtkBox with title and subtitle as described above.
Some of the internal structure of GtkHeaderBar has been made available as public API: GtkWindowHandle and GtkWindowControls. If you have unusual needs for custom headerbars, these might be useful to you.
The ::pack-type child properties of GtkHeaderBar and
GtkActionBar have been removed. If you need to programmatically
place children, use the pack_start()
and pack_end()
APIs. In ui
files, use the type attribute on the child element.
gtk4-builder-tool can help with this conversion, with the –3to4 option of the simplify command.
The child properties of GtkStack, GtkAssistant and GtkNotebook have been converted into child meta objects. 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. The changes to GtkNotebook and GtkAssistant are similar.
gtk4-builder-tool can help with this conversion, with the –3to4 option of the simplify command.
GtkCheckButton is no longer derived from GtkToggleButton. Call
gtk_check_button_set_active()
instead of
gtk_toggle_button_set_active()
.
GtkRadioButton has been removed, and its grouping functionality
has been added to GtkCheckButton and GtkToggleButton. Use
grouped check buttons for traditional radio groups, and used
grouped toggle buttons for view switchers. The new API to set up
groups of buttons is gtk_check_button_set_group()
and
gtk_toggle_button_set_group()
.
gtk4-builder-tool can help with this conversion, with the –3to4 option of the simplify command.
The constructor for GtkScrolledWindow no longer takes the
adjustments as arguments - these were almost always NULL
.
The abstract base class GtkBin for single-child containers has
been removed. The former subclasses are now derived directly
from GtkWidget, and have a “child” property for
their child widget. To add a child, use the setter for the
“child” property (e.g. gtk_frame_set_child()
)
instead of gtk_container_add()
. Adding a child in a ui file with
<child> still works.
The affected classes are:
GtkAspectFrame
GtkButton (and subclasses)
GtkComboBox
GtkFlowBoxChild
GtkFrame
GtkListBoxRow
GtkOverlay
GtkPopover
GtkRevealer
GtkScrolledWindow
GtkSearchBar
GtkViewport
GtkWindow (and subclasses)
If you have custom widgets that were derived from GtkBin, you
should port them to derive from GtkWidget. Notable vfuncs that
you will have to implement include dispose()
(to unparent your
child), compute_expand()
(if you want your container to
propagate expand flags) and get_request_mode()
(if you want your
container to support height-for-width.
You may also want to implement the GtkBuildable interface, to support adding children with <child> in ui files.
The abstract base class GtkContainer for general containers has
been removed. The former subclasses are now derived directly
from GtkWidget, and have class-specific add()
and remove()
functions. The most noticeable change is the use of
gtk_box_append()
or gtk_box_prepend()
instead of
gtk_container_add()
for adding children to GtkBox, and the
change to use container-specific remove functions, such as
gtk_stack_remove()
instead of gtk_container_remove()
. Adding a
child in a ui file with <child> still works.
The affected classes are:
GtkActionBar
GtkBox (and subclasses)
GtkExpander
GtkFixed
GtkFlowBox
GtkGrid
GtkHeaderBar
GtkIconView
GtkInfoBar
GtkListBox
GtkNotebook
GtkPaned
GtkStack
GtkTextView
GtkTreeView
Without GtkContainer, there are no longer facilities for defining and using child properties. If you have custom widgets using child properties, they will have to be converted either to layout properties provided by a layout manager (if they are layout-related), or handled in some other way. One possibility is to use child meta objects, as seen with GtkAssistantPage, GtkStackPage and the like.
The replacements for gtk_container_add()
are:
Widget | Replacement |
---|---|
GtkActionBar |
gtk_action_bar_pack_start() , gtk_action_bar_pack_end()
|
GtkBox |
gtk_box_prepend() , gtk_box_append()
|
GtkExpander |
gtk_expander_set_child()
|
GtkFixed |
gtk_fixed_put()
|
GtkFlowBox |
gtk_flow_box_insert()
|
GtkGrid |
gtk_grid_attach()
|
GtkHeaderBar |
gtk_header_bar_pack_start() , gtk_header_bar_pack_end()
|
GtkIconView | - |
GtkInfoBar |
gtk_info_bar_add_child()
|
GtkListBox |
gtk_list_box_insert()
|
GtkNotebook |
gtk_notebook_append_page()
|
GtkPaned |
gtk_paned_set_start_child() , gtk_paned_set_end_child()
|
GtkStack |
gtk_stack_add_child()
|
GtkTextView |
gtk_text_view_add_child_at_anchor() ,
gtk_text_view_add_overlay()
|
GtkTreeView | - |
GTK 4 has removed the “border-width” property (together with the rest of GtkContainer). Use other means to influence the spacing of your containers, such as the CSS margin and padding properties on child widgets, or the CSS border-spacing property on containers.
Adapt to gtk_widget_destroy()
removal
The function gtk_widget_destroy()
has been removed. To
explicitly destroy a toplevel window, use gtk_window_destroy()
.
To destroy a widget that is part of a hierarchy, remove it from
its parent using a container-specific remove API, such as
gtk_box_remove()
or gtk_stack_remove()
. To destroy a
freestanding non-toplevel widget, use g_object_unref()
to drop
your reference.
A number of APIs that are accepting or returning coordinates
have been changed from ints to doubles:
gtk_widget_translate_coordinates()
, gtk_fixed_put()
,
gtk_fixed_move()
. This change is mostly transparent, except for
cases where out parameters are involved: you need to pass
double* now, instead of int*.
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.
The most commonly used GtkStyleContext API,
gtk_style_context_add_class()
, has been moved to GtkWidget as
gtk_widget_add_css_class()
, as have the corresponding
gtk_style_context_remove_class()
and
gtk_style_context_has_class()
APIs.
In GTK 4, the various GtkCssProvider load functions have lost
their GError argument. If you want to handle CSS loading
errors, use the “parsing-error” signal instead.
gtk_css_provider_get_named()
has been replaced by
gtk_css_provider_load_named()
.
The shadow-type properties in GtkScrolledWindow, GtkViewport, and GtkFrame, as well as the relief properties in GtkButton and its subclasses have been removed. GtkScrolledWindow, GtkButton and GtkMenuButton have instead gained a boolean has-frame property.
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, GTK 4 uses only one virtual
function, GtkWidgetClass::measure()
that widgets have to
implement. gtk_widget_measure()
replaces the various
gtk_widget_get_preferred_ functions for querying sizes.
The GtkWidget.size_allocate()
vfunc takes the baseline as an
argument now, so you no longer need to call
gtk_widget_get_allocated_baseline()
to get it.
The ::size-allocate signal has been removed, since it is easy to misuse. If you need to learn about sizing changes of custom drawing widgets, use the “resize” or “resize” signals. If you want to track the size of toplevel windows, use property notification for “default-width” and “default-height”.
In GTK 4, any widget can have children (and GtkContainer is
gone). There is new API to navigate the widget tree, for use in
widget implementations: gtk_widget_get_first_child()
,
gtk_widget_get_last_child()
, gtk_widget_get_next_sibling()
,
gtk_widget_get_prev_sibling()
.
GTK now supports standard CSS syntax for both linear and radial gradients, just use those.
GTK now supports a more versatile -gtk-icon-filter instead.
Replace
Old | Replacement |
---|---|
-gtk-icon-effect: dim | -gtk-icon-filter: opacity(0.5) |
-gtk-icon-effect: highlight | -gtk-icon-filter: brightness(1.2) |
GTK 4 always uses the current icon theme, with no way to change this.
These non-standard properties have been removed from GTK CSS. Just use regular border radius.
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 “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 connecting a handler to the
“draw” signal.
A number of APIs for querying special-purpose windows have been
removed, since these windows are no longer publicly available:
gtk_tree_view_get_bin_window()
, gtk_viewport_get_bin_window()
,
gtk_viewport_get_view_window()
.
The default value of “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. The only widgets that still need to be
explicitly shown are toplevel windows, dialogs and popovers.
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 “no-show-all”
property and its getter and setter have been removed in GTK 4,
so you should stop using them.
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
instead.
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.
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.
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 “motion-event” or “event” have been removed. All event handling is done via event controllers now.
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.
The “draw” signal has been removed. Widgets need to
implement the GtkWidgetClass.snapshot()
function now.
Connecting draw signal handlers is no longer possible. If you
want to keep using cairo for drawing, use
gtk_snaphot_append_cairo()
.
Observing widget contents and widget size is now done by using the GtkWidgetPaintable object instead of connecting to widget signals.
Instead of a monitor number, GdkMonitor is now used throughout.
gdk_display_get_monitors()
returns the list of monitors that can
be queried or observed for monitors to pass to APIs like
gtk_window_fullscreen_on_monitor()
.
The gdk_monitor_get_workarea()
API is gone. Individual backends
can still provide this information, for example with
gdk_x11_monitor_get_workarea()
.
If you use this information, your code should check which backend is in use and then call the appropriate backend API.
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.
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 “icon-size”.
The :has-padding property is gone, and GtkAssistant no longer adds padding to pages. You can easily do that yourself.
The GtkEditable interface has been made more useful, and the
core functionality of GtkEntry has been broken out as a GtkText
widget. GtkEntry, GtkSearchEntry, GtkSpinButton and the new
GtkPasswordEntry now use a GtkText widget internally and
implement GtkEditable. In particular, this means that it is no
longer possible to use GtkEntry API such as
gtk_entry_grab_focus_without_selecting()
on a search entry.
Use GtkEditable API for editable functionality, and
widget-specific APIs for things that go beyond the common
interface. For password entries, use GtkPasswordEntry. As an
example, gtk_spin_button_set_max_width_chars()
has been removed
in favor of gtk_editable_set_max_width_chars()
.
The GtkOverlay :pass-through child property has been replaced by the “can-target” property. Note that they have the opposite sense: pass-through == !can-target.
Since GtkScrolledWindow can deal with widgets that do not implement the GtkScrollable interface by automatically wrapping them into a GtkViewport, GtkLayout is redundant, and has been removed in favor of the existing GtkFixed container widget.
The way search entries are connected to global events has
changed; gtk_search_entry_handle_event()
has been dropped and
replaced by gtk_search_entry_set_key_capture_widget()
and
gtk_event_controller_key_forward()
.
The default value of “draw-value” has been changed to
FALSE
. If you want your scales to draw values, you will have to
set this property explicitly now.
gtk4-builder-tool can help with this conversion, with the –3to4 option of the simplify command.
Stop using gtk_window_activate_default()
The handling of default widgets has been changed, and activating
the default now works by calling gtk_widget_activate_default()
on the widget that caused the activation. If you have a custom
widget that wants to override the default handling, you can
provide an implementation of the default.activate action in your
widgets’ action groups.
Stop using gtk_widget_grab_default()
The function gtk_widget_grab_default()
has been removed. If you
need to mark a widget as default, use
gtk_window_set_default_widget()
directly.
The special handling for the ::has-default and ::has-focus properties has been removed. If you want to define the initial focus or the the default widget in a .ui file, set the ::default-widget or ::focus-widget properties of the toplevel window.
To track the current display, use the “root” property instead.
The modal property has been renamed to autohide. gtk-builder-tool can assist with the rename in ui files.
gtk_widget_get_surface()
has been removed. Use
gtk_native_get_surface()
in combination with
gtk_widget_get_native()
instead.
gtk_widget_is_toplevel()
has been removed. Use GTK_IS_ROOT,
GTK_IS_NATIVE or GTK_IS_WINDOW instead, as appropriate.
gtk_widget_get_toplevel()
has been removed. Use
gtk_widget_get_root()
or gtk_widget_get_native()
instead, as
appropriate.
To allow signal handlers to access the deleted text before it
has been deleted “deleted-text” has changed from
G_SIGNAL_RUN_FIRST
to G_SIGNAL_RUN_LAST
. The default handler
removes the text from the GtkEntryBuffer.
To adapt existing code, use g_signal_connect_after()
or
G_CONNECT_AFTER
when using g_signal_connect_data()
or
g_signal_connect_object()
.
These widgets were heavily relying on X11-centric concepts such as override-redirect windows and grabs, and were hard to adjust to other windowing systems.
Menus can already be replaced using GtkPopoverMenu in GTK 3. Additionally, GTK 4 introduces GtkPopoverMenuBar to replace menubars. These new widgets can only be constructed from menu models, so the porting effort involves switching to menu models and actions.
Tabular menus were rarely used and complicated the menu code, so they have not been brought over to GtkPopoverMenu. If you need complex layout in menu-like popups, consider directly using a GtkPopover instead.
Since menus are gone, GtkMenuButton also lost its ability to show menus, and needs to be used with popovers in GTK 4.
Toolbars were using outdated concepts such as requiring special toolitem widgets. Toolbars should be replaced by using a GtkBox with regular widgets instead and the “toolbar” style class.
GtkAspectFrame is no longer derived from GtkFrame and does not place a label and frame around its child anymore. It still lets you control the aspect ratio of its child.
Tooltips no longer use GtkWindows in GTK 4, and it is no longer
possible to provide a custom window for tooltips. Replacing the
content of the tooltip with a custom widget is still possible,
with gtk_tooltip_set_custom()
.
The source-side Drag-and-Drop apis in GTK 4 have been changed to
use an event controller, GtkDragSource. Instead of calling
gtk_drag_source_set()
and connecting to GtkWidget signals, you
create a GtkDragSource object, attach it to the widget with
gtk_widget_add_controller()
, and connect to GtkDragSource
signals. Instead of calling gtk_drag_begin()
on a widget to
start a drag manually, call gdk_drag_begin()
. The
::drag-data-get signal has been replaced by the
“prepare” signal, which returns a
GdkContentProvider for the drag operation.
The destination-side Drag-and-Drop API in GTK 4 have also been
changed to use an event controller, GtkDropTarget. Instead of
calling gtk_drag_dest_set()
and connecting to GtkWidget
signals, you create a GtkDropTarget object, attach it to the
widget with gtk_widget_add_controller()
, and connect to
GtkDropTarget signals. The ::drag-motion signal has been
renamed to “accept”, and instead of
::drag-data-received, you need to use async read methods on the
GdkDrop object, such as gdk_drop_read_async()
or
gdk_drop_read_value_async()
.
gtk_icon_theme_lookup_icon()
returns a GtkIconPaintable object
now, instead of a GtkIconInfo. It always returns a paintable in
the requested size, and never fails. A number of
no-longer-relevant lookup flags and API variants have been
removed.
Note that while GTK 4 is moving towards GdkPaintable as a
primary API for paintable content, it is meant to be a
“pure” content producer, therefore a
GtkIconPaintable for a symbolic icon will
not get recolored depending on the context
it is rendered it. To properly render a symbolic icon that is
provided in the form of a GtkIconPaintable (this can be checked
with gtk_icon_paintable_is_symbolic()
), you have to call
gtk_icon_paintable_get_icon_name()
and set the icon name on a
GtkImage.
GtkFileChooser moved to a GFile-based API. If you need to
convert a path or a URI, use g_file_new_for_path()
,
g_file_new_for_commandline_arg()
, or g_file_new_for_uri()
;
similarly, if you need to get a path, name or URI from a GFile,
use g_file_get_path()
, g_file_get_basename()
or
g_file_get_uri()
. With the removal or path and URI-based
functions, the “local-only” property has been
removed; GFile can be used to access non-local as well as local
resources.
The GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER action has been
removed. Use GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
, instead. If
a new folder is needed, the user can create one.
The “confirm-overwrite” signal, and the “do-overwrite-confirmation” property have been removed from GtkFileChooser. The file chooser widgets will automatically handle the confirmation of overwriting a file when using GTK_FILE_CHOOSER_ACTION_SAVE.
GtkFileChooser does not support a custom extra widget any more.
If you need to add extra widgets, use
gtk_file_chooser_add_choice()
instead.
GtkFileChooser does not support a custom preview widget any more. If you need to show a custom preview, you can create your own GtkDialog with a GtkFileChooserWidget and your own preview widget that you update whenever the “selection-changed” signal is emitted.
GtkDialog, GtkNativeDialog, and GtkPrintOperation removed their blocking API using nested main loops. Nested main loops present re-entrancy issues and other hard to debug issues when coupled with other event sources (IPC, accessibility, network operations) that are not under the toolkit or the application developer’s control. Additionally, “stop-the-world” functions do not fit the event-driven programming model of GTK.
You can replace calls to gtk_dialog_run()
by specifying that the
GtkDialog must be modal using gtk_window_set_modal()
or the
GTK_DIALOG_MODAL
flag, and connecting to the
“response” signal.
All the GtkBuildable API was made private, except for the getter
function to retrieve the buildable ID. If you are using
gtk_buildable_get_name()
you should replace it with
gtk_buildable_get_buildable_id()
.
GtkAboutDialog now directly derives from GtkWindow, the GtkDialog API can no longer be used on it.
The getter functions for retrieving the data from GtkTreeView and GtkIconView inside a “query-tooltip” signal do not take the pointer coordinates as inout arguments any more, but as normal in ones.
See: gtk_tree_view_get_tooltip_context()
,
gtk_icon_view_get_tooltip_context()
The GtkFileChooserButton
widget was removed,
due to its shortcomings in the user interaction. You can replace
it with a simple GtkButton that shows a GtkFileChooserNative
dialog when clicked; once the file selection has completed, you
can update the label of the GtkButton with the selected file.
In GTK 3 the “gtk-cursor-aspect-ratio” property of GtkSettings was a float. In GTK 4 this has been changed to a double.