<chapter id="gtk-migrating-3-to-4">
  <title>Migrating from GTK 3.x to GTK 4</title>
  <para>
    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 number of adjustments that you may have to do when
    you actually switch your application to build against GTK 4.
  </para>
  <sect1>
    <title>Preparation in GTK 3.x</title>
    <para>
      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 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.
    </para>
    <sect2>
      <title>Do not use deprecated symbols</title>
      <para>
        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
        <ulink url="https://developer.gnome.org/gtk3/3.24/api-index-deprecated.html">index</ulink>
        of all deprecated symbols.
      </para>
      <para>
        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:
      </para>
      <programlisting>
make CFLAGS+=&quot;-DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED&quot;
</programlisting>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Enable diagnostic warnings</title>
      <para>
        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 <literal>G_ENABLE_DIAGNOSTIC</literal> environment
        variable when running your application, e.g.:
      </para>
      <programlisting>
G_ENABLE_DIAGNOSTIC=1 ./your-app
</programlisting>
    </sect2>
    <sect2>
      <title>Do not use GTK-specific command line arguments</title>
      <para>
        GTK4 does not parse command line arguments any more. If you are
        using command line arguments like <literal>--gtk-debug</literal>
        you should use the <literal>GTK_DEBUG</literal> environment
        variable instead. If you are using
        <literal>--g-fatal-warnings</literal> for debugging purposes,
        you should use the <literal>G_DEBUG</literal> environment
        variable, as specified by the
        <ulink url="https://developer.gnome.org/glib/stable/glib-running.html">GLib
        documentation</ulink>.
      </para>
    </sect2>
    <sect2>
      <title>Do not use widget style properties</title>
      <para>
        Style properties do not exist in GTK 4. You should stop using
        them in your custom CSS and in your code.
      </para>
    </sect2>
    <sect2>
      <title>Review your window creation flags</title>
      <para>
        GTK 4 removes the <literal>GDK_WA_CURSOR</literal> flag.
        Instead, just use <link linkend="gdk-window-set-cursor"><function>gdk_window_set_cursor()</function></link> to set a cursor on the
        window after creating it. GTK 4 also removes the
        <literal>GDK_WA_VISUAL</literal> flag, and always uses an RGBA
        visual for windows. To prepare your code for this, use
        <literal>gdk_window_set_visual (<link linkend="gdk-screen-get-rgba-visual"><function>gdk_screen_get_rgba_visual()</function></link>)</literal>
        after creating your window. GTK 4 also removes the
        <literal>GDK_WA_WMCLASS</literal> flag. If you need this
        X11-specific functionality, use <link linkend="XSetClassHint"><function>XSetClassHint()</function></link> directly.
      </para>
    </sect2>
    <sect2>
      <title>Stop using direct access to GdkEvent structs</title>
      <para>
        In GTK 4, event structs are opaque and immutable. Many fields
        already have accessors in GTK 3, and you should use those to
        reduce the amount of porting work you have to do at the time of
        the switch.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <link linkend="gdk-pointer-warp"><function>gdk_pointer_warp()</function></link></title>
      <para>
        Warping the pointer is disorienting and unfriendly to users. GTK
        4 does not support it. In special circumstances (such as when
        implementing remote connection UIs) it can be necessary to warp
        the pointer; in this case, use platform APIs such as
        <link linkend="XWarpPointer"><function>XWarpPointer()</function></link> directly.
      </para>
    </sect2>
    <sect2>
      <title>Stop using non-RGBA visuals</title>
      <para>
        GTK 4 always uses RGBA visuals for its windows; you should make
        sure that your code works with such visuals. At the same time,
        you should stop using GdkVisual APIs, since this object not
        longer exists in GTK 4. Most of its APIs are deprecated already
        and not useful when dealing with RGBA visuals.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkBox padding, fill and expand child
      properties</title>
      <para>
        GTK 4 removes these <link linkend="GtkBox"><type>GtkBox</type></link> child properties, so you should stop
        using them. You can replace GtkBox:padding using the
        <link linkend="GtkWidget--margin"><type>“margin”</type></link> properties on your <link linkend="GtkBox"><type>GtkBox</type></link> child widgets.
      </para>
      <para>
        The fill child property can be replaced by setting appropriate
        values for the <link linkend="GtkWidget--halign"><type>“halign”</type></link> and <link linkend="GtkWidget--valign"><type>“valign”</type></link>
        properties of the child widgets. If you previously set the fill
        child property to <link linkend="TRUE:CAPS"><literal>TRUE</literal></link>, you can achieve the same effect by
        setting the halign or valign properties to <link linkend="GTK-ALIGN-FILL:CAPS"><literal>GTK_ALIGN_FILL</literal></link>,
        depending on the parent box – halign for a horizontal box,
        valign for a vertical one.
      </para>
      <para>
        <link linkend="GtkBox"><type>GtkBox</type></link> also uses the expand child property. It can be replaced
        by setting <link linkend="GtkWidget--hexpand"><type>“hexpand”</type></link> or <link linkend="GtkWidget--vexpand"><type>“vexpand”</type></link> on the child
        widgets. To match the old behavior of the <link linkend="GtkBox"><type>GtkBox</type></link>’s expand child
        property, you need to set <link linkend="GtkWidget--hexpand"><type>“hexpand”</type></link> on the child
        widgets of a horizontal <link linkend="GtkBox"><type>GtkBox</type></link> and <link linkend="GtkWidget--vexpand"><type>“vexpand”</type></link> on the
        child widgets of a vertical <link linkend="GtkBox"><type>GtkBox</type></link>.
      </para>
      <para>
        Note that there’s a subtle but important difference between
        <link linkend="GtkBox"><type>GtkBox</type></link>’s expand and fill child properties and the ones in
        <link linkend="GtkWidget"><type>GtkWidget</type></link>: setting <link linkend="GtkWidget--hexpand"><type>“hexpand”</type></link> or <link linkend="GtkWidget--vexpand"><type>“vexpand”</type></link> to
        <link linkend="TRUE:CAPS"><literal>TRUE</literal></link> will propagate up the widget hierarchy, so a pixel-perfect
        port might require you to reset the expansion flags to <link linkend="FALSE:CAPS"><literal>FALSE</literal></link> in
        a parent widget higher up the hierarchy.
      </para>
    </sect2>
    <sect2>
      <title>Stop using the state argument of GtkStyleContext
      getters</title>
      <para>
        The getters in the GtkStyleContext API, such as
        <link linkend="gtk-style-context-get-property"><function>gtk_style_context_get_property()</function></link>, <link linkend="gtk-style-context-get"><function>gtk_style_context_get()</function></link>, or
        <link linkend="gtk-style-context-get-color"><function>gtk_style_context_get_color()</function></link> only accept the context’s current
        state for their state argument. You should update all callers to
        pass the current state.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <link linkend="gdk-pixbuf-get-from-window"><function>gdk_pixbuf_get_from_window()</function></link> and
      <link linkend="gdk-cairo-set-source-surface"><function>gdk_cairo_set_source_surface()</function></link></title>
      <para>
        These functions are not supported in GTK 4. Instead, either use
        backend-specific APIs, or render your widgets using
        <link linkend="GtkWidgetClass.snapshot"><function>GtkWidgetClass.snapshot()</function></link> (once you are using GTK 4).
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkButton’s image-related API</title>
      <para>
        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
        <link linkend="gtk-button-new-from-icon-name"><function>gtk_button_new_from_icon_name()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkWidget event signals</title>
      <para>
        Event controllers and gestures replace event signals in GTK 4.
      </para>
      <para>
        Most of them have been backported to GTK 3.x so you can prepare
        for this change.
      </para>
      <informaltable>
        <tgroup cols="2">
          <colspec align="left" />
          <colspec align="left" />
          <thead>
            <row>
              <entry>
                Signal
              </entry>
              <entry>
                Event controller
              </entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>
                ::event
              </entry>
              <entry>
                <link linkend="GtkEventControllerLegacy"><type>GtkEventControllerLegacy</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::event-after
              </entry>
              <entry>
                <link linkend="GtkEventControllerLegacy"><type>GtkEventControllerLegacy</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::button-press-event
              </entry>
              <entry>
                <link linkend="GtkGestureClick"><type>GtkGestureClick</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::button-release-event
              </entry>
              <entry>
                <link linkend="GtkGestureClick"><type>GtkGestureClick</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::touch-event
              </entry>
              <entry>
                various touch gestures
              </entry>
            </row>
            <row>
              <entry>
                ::scroll-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerScroll"><type>GtkEventControllerScroll</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::motion-notify-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerMotion"><type>GtkEventControllerMotion</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::delete-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::key-press-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerKey"><type>GtkEventControllerKey</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::key-release-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerKey"><type>GtkEventControllerKey</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::enter-notify-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerMotion"><type>GtkEventControllerMotion</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::leave-notify-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerMotion"><type>GtkEventControllerMotion</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::configure-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::focus-in-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerFocus"><type>GtkEventControllerFocus</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::focus-out-event
              </entry>
              <entry>
                <link linkend="GtkEventControllerFocus"><type>GtkEventControllerFocus</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::map-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::unmap-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::property-notify-event
              </entry>
              <entry>
                replaced by <link linkend="GdkClipboard"><type>GdkClipboard</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::selection-clear-event
              </entry>
              <entry>
                replaced by <link linkend="GdkClipboard"><type>GdkClipboard</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::selection-request-event
              </entry>
              <entry>
                replaced by <link linkend="GdkClipboard"><type>GdkClipboard</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::selection-notify-event
              </entry>
              <entry>
                replaced by <link linkend="GdkClipboard"><type>GdkClipboard</type></link>
              </entry>
            </row>
            <row>
              <entry>
                Drag-and-Drop signals
              </entry>
              <entry>
                <link linkend="GtkDragSource"><type>GtkDragSource</type></link>, <link linkend="GtkDropTarget"><type>GtkDropTarget</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::proximity-in-event
              </entry>
              <entry>
                <link linkend="GtkGestureStylus"><type>GtkGestureStylus</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::proximity-out-event
              </entry>
              <entry>
                <link linkend="GtkGestureStylus"><type>GtkGestureStylus</type></link>
              </entry>
            </row>
            <row>
              <entry>
                ::visibility-notify-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::window-state-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::damage-event
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                ::grab-broken-event
              </entry>
              <entry>
                -
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
      <para>
        Event signals which are not directly related to input have to be
        dealt with on a one-by-one basis. If you were using
        ::configure-event and ::window-state-event to save window state,
        you should use property notification for corresponding GtkWindow
        properties, such as <link linkend="GtkWindow--default-width"><type>“default-width”</type></link>,
        <link linkend="GtkWindow--default-height"><type>“default-height”</type></link>, <link linkend="GtkWindow--maximized"><type>“maximized”</type></link> or
        <link linkend="GtkWindow--fullscreened"><type>“fullscreened”</type></link>.
      </para>
    </sect2>
    <sect2>
      <title>Set a proper application ID</title>
      <para>
        In GTK 4 we want the application’s <link linkend="GApplication"><type>GApplication</type></link>
        <quote>application-id</quote> (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 GTK 3.x call
        <link linkend="g-set-prgname"><function>g_set_prgname()</function></link> with the same application ID you passed to
        <link linkend="GtkApplication"><type>GtkApplication</type></link>. Rename your desktop files to match the
        application ID if needed.
      </para>
      <para>
        The call to <link linkend="g-set-prgname"><function>g_set_prgname()</function></link> can be removed once you fully
        migrated to GTK 4.
      </para>
      <para>
        You should be aware that changing the application ID makes your
        application appear as a new, different app to application
        installers. You should consult the appstream documentation for
        best practices around renaming applications.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <link linkend="gtk-main"><function>gtk_main()</function></link> and related APIs</title>
      <para>
        GTK 4 removes the gtk_main_ family of APIs. The recommended
        replacement is GtkApplication, but you can also iterate the GLib
        mainloop directly, using GMainContext APIs. The replacement for
        <link linkend="gtk-events-pending"><function>gtk_events_pending()</function></link> is <link linkend="g-main-context-pending"><function>g_main_context_pending()</function></link>, the
        replacement for <link linkend="gtk-main-iteration"><function>gtk_main_iteration()</function></link> is
        <link linkend="g-main-context-iteration"><function>g_main_context_iteration()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Reduce the use of <link linkend="gtk-widget-destroy"><function>gtk_widget_destroy()</function></link></title>
      <para>
        GTK 4 introduces a <link linkend="gtk-window-destroy"><function>gtk_window_destroy()</function></link> api. While that is not
        available in GTK 3, you can prepare for the switch by using
        <link linkend="gtk-widget-destroy"><function>gtk_widget_destroy()</function></link> only on toplevel windows, and replace all
        other uses with <link linkend="gtk-container-remove"><function>gtk_container_remove()</function></link> or <link linkend="g-object-unref"><function>g_object_unref()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Reduce the use of generic container APIs</title>
      <para>
        GTK 4 removes <link linkend="gtk-container-add"><function>gtk_container_add()</function></link> and <link linkend="gtk-container-remove"><function>gtk_container_remove()</function></link>.
        While there is not always a replacement for
        <link linkend="gtk-container-remove"><function>gtk_container_remove()</function></link> in GTK 3, you can replace many uses of
        <link linkend="gtk-container-add"><function>gtk_container_add()</function></link> with equivalent container-specific APIs such
        as <link linkend="gtk-box-pack-start"><function>gtk_box_pack_start()</function></link> or <link linkend="gtk-grid-attach"><function>gtk_grid_attach()</function></link>, and thereby reduce
        the amount of work you have to do at the time of the switch.
      </para>
    </sect2>
    <sect2>
      <title>Review your use of icon resources</title>
      <para>
        When using icons as resources, the behavior of GTK 4 is
        different in one respect: Icons that are directly in
        $APP_ID/icons/ are treated as unthemed icons, which also means
        that symbolic icons are not recolored. If you want your icon
        resources to have icon theme semantics, they need to be placed
        into theme subdirectories such as $APP_ID/icons/16x16/actions or
        $APP_ID/icons/scalable/status.
      </para>
      <para>
        This location works fine in GTK 3 too, so you can prepare for
        this change before switching to GTK 4.
      </para>
    </sect2>
  </sect1>
  <sect1>
    <title>Changes that need to be done at the time of the
    switch</title>
    <para>
      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.
    </para>
    <sect2>
      <title>Larger changes</title>
      <para>
        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.
      </para>
      <sect3>
        <title>Subclassing</title>
        <para>
          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.
        </para>
      </sect3>
      <sect3>
        <title>Life-cycle handling</title>
        <para>
          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. <link linkend="gtk-window-destroy"><function>gtk_window_destroy()</function></link> 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.
        </para>
        <para>
          The <link linkend="GtkWidget-destroy"><type>“destroy”</type></link> 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.
        </para>
      </sect3>
    </sect2>
    <sect2>
      <title>Stop using GdkScreen</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Stop using the root window</title>
      <para>
        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
        <link linkend="gdk-x11-display-get-xrootwindow"><function>gdk_x11_display_get_xrootwindow()</function></link> to get its XID.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GdkVisual</title>
      <para>
        This object is not useful with current GTK drawing APIs and has
        been removed without replacement.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GdkDeviceManager</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GdkWindow API changes</title>
      <para>
        GdkWindow has been renamed to GdkSurface.
      </para>
      <para>
        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, <link linkend="GdkToplevel"><type>GdkToplevel</type></link> and <link linkend="GdkPopup"><type>GdkPopup</type></link>.
        Surfaces implementing these interfaces are created with
        <link linkend="gdk-surface-new-toplevel"><function>gdk_surface_new_toplevel()</function></link> and <link linkend="gdk-surface-new-popup"><function>gdk_surface_new_popup()</function></link>,
        respectively, and they are presented on screen using
        <link linkend="gdk-toplevel-present"><function>gdk_toplevel_present()</function></link> and <link linkend="gdk-popup-present"><function>gdk_popup_present()</function></link>. The <link linkend="present"><function>present()</function></link>
        functions take parameters in the form of an auxiliary layout
        struct, <link linkend="GdkPopupLayout"><type>GdkPopupLayout</type></link> or <link linkend="GdkToplevelLayout"><type>GdkToplevelLayout</type></link>. 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.
      </para>
      <para>
        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.
      </para>
      <para>
        Subsurfaces are only supported with the Wayland backend, using
        <link linkend="gdk-wayland-surface-new-subsurface"><function>gdk_wayland_surface_new_subsurface()</function></link>. Native and foreign
        subwindows are no longer supported. These concepts were
        complicating the code and could not be supported across
        backends.
      </para>
      <para>
        A number of GdkWindow APIs are no longer available. This
        includes <link linkend="gdk-window-reparent"><function>gdk_window_reparent()</function></link>, <link linkend="gdk-window-set-geometry-hints"><function>gdk_window_set_geometry_hints()</function></link>,
        <link linkend="gdk-window-raise"><function>gdk_window_raise()</function></link>, <link linkend="gdk-window-restack"><function>gdk_window_restack()</function></link>, <link linkend="gdk-window-move"><function>gdk_window_move()</function></link>,
        <link linkend="gdk-window-resize"><function>gdk_window_resize()</function></link>. If you need to manually control the
        position or stacking of your X11 windows, you you will have to
        use Xlib apis.
      </para>
      <para>
        A number of minor API cleanups have happened in GdkSurface as
        well. For example, <link linkend="gdk-surface-input-shape-combine-region"><function>gdk_surface_input_shape_combine_region()</function></link> has
        been renamed to <link linkend="gdk-surface-set-input-region"><function>gdk_surface_set_input_region()</function></link>, and
        <link linkend="gdk-surface-begin-resize-drag"><function>gdk_surface_begin_resize_drag()</function></link> has been renamed to
        <link linkend="gdk-toplevel-begin-resize"><function>gdk_toplevel_begin_resize()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>The <quote>iconified</quote> window state has been renamed
      to <quote>minimized</quote></title>
      <para>
        The <link linkend="GDK-TOPLEVEL-STATE-ICONIFIED:CAPS"><literal>GDK_TOPLEVEL_STATE_ICONIFIED</literal></link> value of the <link linkend="GdkSurfaceState"><type>GdkSurfaceState</type></link>
        enumeration is now <link linkend="GDK-TOPLEVEL-STATE-MINIMIZED:CAPS"><literal>GDK_TOPLEVEL_STATE_MINIMIZED</literal></link> in the
        <link linkend="GdkToplevelState"><type>GdkToplevelState</type></link> enumeration.
      </para>
      <para>
        The <link linkend="GdkWindow"><type>GdkWindow</type></link> functions <link linkend="gdk-window-iconify"><function>gdk_window_iconify()</function></link> and
        <link linkend="gdk-window-deiconify"><function>gdk_window_deiconify()</function></link> have been renamed to
        <link linkend="gdk-toplevel-minimize"><function>gdk_toplevel_minimize()</function></link> and <link linkend="gdk-toplevel-present"><function>gdk_toplevel_present()</function></link>,
        respectively.
      </para>
      <para>
        The behavior of the minimization and unminimization operations
        have not been changed, and they still require support from the
        underlying windowing system.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GdkEvent API changes</title>
      <para>
        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.
      </para>
      <para>
        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 <link linkend="gdk-event-get-history"><function>gdk_event_get_history()</function></link> on the latest event.
      </para>
    </sect2>
    <sect2>
      <title>Stop using grabs</title>
      <para>
        GTK 4 no longer provides the <link linkend="gdk-device-grab"><function>gdk_device_grab()</function></link> or
        <link linkend="gdk-seat-grab"><function>gdk_seat_grab()</function></link> apis. If you need to dismiss a popup when the
        user clicks outside (the most common use for grabs), you can use
        the GdkPopup <link linkend="GdkPopup--autohide"><type>“autohide”</type></link> property instead. GtkPopover
        also has a <link linkend="GtkPopover--autohide"><type>“autohide”</type></link> property for this. If you need
        to prevent the user from interacting with a window while a
        dialog is open, use the <link linkend="GtkWindow--modal"><type>“modal”</type></link> property of the dialog.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to coordinate API changes</title>
      <para>
        A number of coordinate APIs in GTK 3 had _double variants:
        <link linkend="gdk-device-get-surface-at-position"><function>gdk_device_get_surface_at_position()</function></link>,
        <link linkend="gdk-surface-get-device-position"><function>gdk_surface_get_device_position()</function></link>. These have been changed to
        use doubles, and the _double variants have been removed. Update
        your code accordingly.
      </para>
      <para>
        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 <link linkend="gdk-surface-get-origin"><function>gdk_surface_get_origin()</function></link>,
        <link linkend="gdk-surface-move"><function>gdk_surface_move()</function></link> or <link linkend="gdk-event-get-root-coords"><function>gdk_event_get_root_coords()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GdkKeymap API changes</title>
      <para>
        GdkKeymap no longer exists as an independent object.
      </para>
      <para>
        If you need access to keymap state, it is now exposed as
        properties on the <link linkend="GdkDevice"><type>GdkDevice</type></link> representing the keyboard:
        <link linkend="GdkDevice--direction"><type>“direction”</type></link>, <link linkend="GdkDevice--has-bidi-layouts"><type>“has-bidi-layouts”</type></link>,
        <link linkend="GdkDevice--caps-lock-state"><type>“caps-lock-state”</type></link>, <link linkend="GdkDevice--num-lock-state"><type>“num-lock-state”</type></link>,
        <link linkend="GdkDevice--scroll-lock-state"><type>“scroll-lock-state”</type></link> and <link linkend="GdkDevice--modifier-state"><type>“modifier-state”</type></link>. To
        obtain the keyboard device, you can use
        <literal>gdk_seat_get_keyboard (gdk_display_get_default_seat (display)</literal>.
      </para>
      <para>
        If you need access to translated keys for event handling,
        <link linkend="GdkEvent"><type>GdkEvent</type></link> now includes all of the translated key state,
        including consumed modifiers, group and shift level, so there
        should be no need to manually call
        <link linkend="gdk-keymap-translate-keyboard-state"><function>gdk_keymap_translate_keyboard_state()</function></link> (which has been removed).
      </para>
      <para>
        If you need to do forward or backward mapping between key codes
        and key values, use <link linkend="gdk-display-map-keycode"><function>gdk_display_map_keycode()</function></link> and
        <link linkend="gdk-display-map-keyval"><function>gdk_display_map_keyval()</function></link>, which are the replacements for
        <link linkend="gdk-keymap-get-entries-for-keycode"><function>gdk_keymap_get_entries_for_keycode()</function></link> and
        <link linkend="gdk-keymap-get-entries-for-keyval"><function>gdk_keymap_get_entries_for_keyval()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changes in keyboard modifier handling</title>
      <para>
        GTK 3 has the idea that use of modifiers may differ between
        different platforms, and has a <link linkend="GdkModifierIntent"><type>GdkModifierIntent</type></link> api to let
        platforms provide hint about how modifiers are expected to be
        used. It also promoted the use of
        <literal>&lt;Primary&gt;</literal> instead of
        <literal>&lt;Control&gt;</literal> to specify accelerators that
        adapt to platform conventions.
      </para>
      <para>
        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:
      </para>
      <variablelist spacing="compact">
        <varlistentry>
          <term>
            GDK_CONTROL_MASK
          </term>
          <listitem>
            <para>
              Primary accelerators
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>
            GDK_ALT_MASK
          </term>
          <listitem>
            <para>
              Mnemonics
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>
            GDK_SHIFT_MASK
          </term>
          <listitem>
            <para>
              Extending selections
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>
            GDK_CONTROL_MASK
          </term>
          <listitem>
            <para>
              Modifying selections
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>
            GDK_CONTROL_MASK|GDK_ALT_MASK
          </term>
          <listitem>
            <para>
              Prevent text input
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>
        Consequently, <link linkend="GdkModifierIntent"><type>GdkModifierIntent</type></link> and related APIs have been
        removed, and <literal>&lt;Control&gt;</literal> is preferred
        over <literal>&lt;Primary&gt;</literal> in accelerators.
      </para>
      <para>
        A related change is that GTK 4 no longer supports the use of
        archaic X11 <quote>real</quote> modifiers with the names Mod1,…,
        Mod5, and <link linkend="GDK-MOD1-MASK:CAPS"><literal>GDK_MOD1_MASK</literal></link> has been renamed to <link linkend="GDK-ALT-MASK:CAPS"><literal>GDK_ALT_MASK</literal></link>.
      </para>
    </sect2>
    <sect2>
      <title>Replace GtkClipboard with GdkClipboard</title>
      <para>
        The <literal>GtkClipboard</literal> API has been removed, and
        replaced by <link linkend="GdkClipboard"><type>GdkClipboard</type></link>. 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 <link linkend="GValue"><type>GValue</type></link>
        like object properties, instead of opaque identifiers, so it
        should be easier to use.
      </para>
      <para>
        For instance, the example below copies the contents of an entry
        into the clipboard:
      </para>
      <programlisting>
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 (&amp;value, G_TYPE_STRING);
  g_value_set_string (&amp;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, &amp;value);

  g_value_unset (&amp;value);
}
</programlisting>
      <para>
        whereas the example below pastes the contents into the entry:
      </para>
      <programlisting>
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 (&amp;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, &amp;value, NULL))
    return;

  const char *str = g_value_get_string (&amp;value);

  gtk_editable_set_text (editable, str);

  g_value_unset (&amp;value);
}
</programlisting>
      <para>
        The convenience API for specific target types in
        <literal>GtkClipboard</literal> has been replaced by their
        corresponding GType:
      </para>
      <informaltable>
        <tgroup cols="2">
          <colspec align="left" />
          <colspec align="left" />
          <thead>
            <row>
              <entry>
                GtkClipboard
              </entry>
              <entry>
                GType
              </entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>
                <literal><link linkend="gtk-clipboard-request-text"><function>gtk_clipboard_request_text()</function></link></literal>
              </entry>
              <entry>
                <literal>G_TYPE_STRING</literal>
              </entry>
            </row>
            <row>
              <entry>
                <literal><link linkend="gtk-clipboard-request-rich-text"><function>gtk_clipboard_request_rich_text()</function></link></literal>
              </entry>
              <entry>
                <literal>GTK_TYPE_TEXT_BUFFER</literal>
              </entry>
            </row>
            <row>
              <entry>
                <literal><link linkend="gtk-clipboard-request-image"><function>gtk_clipboard_request_image()</function></link></literal>
              </entry>
              <entry>
                <literal>GDK_TYPE_PIXBUF</literal>
              </entry>
            </row>
            <row>
              <entry>
                <literal><link linkend="gtk-clipboard-request-uris"><function>gtk_clipboard_request_uris()</function></link></literal>
              </entry>
              <entry>
                <literal>GDK_TYPE_FILE_LIST</literal>
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
      <para>
        <emphasis role="strong">Note</emphasis>: Support for rich text
        serialization across different processes for <link linkend="GtkTextBuffer"><type>GtkTextBuffer</type></link> is
        not available any more.
      </para>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <literal>gtk_get_current_...</literal>
      APIs</title>
      <para>
        The function <link linkend="gtk-get-current-event"><function>gtk_get_current_event()</function></link> and its variants have been
        replaced by equivalent event controller APIs:
        <link linkend="gtk-event-controller-get-current-event"><function>gtk_event_controller_get_current_event()</function></link>, etc.
      </para>
    </sect2>
    <sect2>
      <title>Convert your ui files</title>
      <para>
        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.
      </para>
      <para>
        The &lt;requires&gt; tag now supports for the <quote>lib</quote>
        attribute the <quote>gtk</quote> value only, instead of the
        <quote>gtk+</quote> one previously.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkBuilder API changes</title>
      <para>
        <link linkend="gtk-builder-connect-signals"><function>gtk_builder_connect_signals()</function></link> no longer exists. Instead, signals
        are always connected automatically. If you need to add user data
        to your signals, <link linkend="gtk-builder-set-current-object"><function>gtk_builder_set_current_object()</function></link> must be
        called. An important caveat is that you have to do this before
        loading any XML. This means if you need to use
        <link linkend="gtk-builder-set-current-object"><function>gtk_builder_set_current_object()</function></link>, you can no longer use
        <link linkend="gtk-builder-new-from-file"><function>gtk_builder_new_from_file()</function></link>, <link linkend="gtk-builder-new-from-resource"><function>gtk_builder_new_from_resource()</function></link>, or
        <link linkend="gtk-builder-new-from-string"><function>gtk_builder_new_from_string()</function></link>. Instead, you must use vanilla
        <link linkend="gtk-builder-new"><function>gtk_builder_new()</function></link>, then call <link linkend="gtk-builder-set-current-object"><function>gtk_builder_set_current_object()</function></link>,
        then load the XML using <link linkend="gtk-builder-add-from-file"><function>gtk_builder_add_from_file()</function></link>,
        <link linkend="gtk-builder-add-from-resource"><function>gtk_builder_add_from_resource()</function></link>, or
        <link linkend="gtk-builder-add-from-string"><function>gtk_builder_add_from_string()</function></link>. You must check the return value
        for failure and manually abort with <link linkend="g-error"><function>g_error()</function></link> if something went
        wrong.
      </para>
      <para>
        You only have to worry about this if you were previously using
        <link linkend="gtk-builder-connect-signals"><function>gtk_builder_connect_signals()</function></link>. If you are using templates, then
        <link linkend="gtk-widget-init-template"><function>gtk_widget_init_template()</function></link> will call
        <link linkend="gtk-builder-set-current-object"><function>gtk_builder_set_current_object()</function></link> for you, so templates work like
        before.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to event controller API changes</title>
      <para>
        A few changes to the event controller and <link linkend="GtkGesture"><type>GtkGesture</type></link> 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
        <link linkend="GtkEventControllerMotion-enter"><type>“enter”</type></link> and
        <link linkend="GtkEventControllerMotion-leave"><type>“leave”</type></link> signals have gained new
        arguments. Another is that <link linkend="GtkGestureMultiPress"><type>GtkGestureMultiPress</type></link> has been
        renamed to <link linkend="GtkGestureClick"><type>GtkGestureClick</type></link>, and has lost its area property. A
        <link linkend="GtkEventControllerFocus"><type>GtkEventControllerFocus</type></link> has been split off from
        <link linkend="GtkEventcontrollerKey"><type>GtkEventcontrollerKey</type></link>.
      </para>
      <para>
        In GTK 3, <link linkend="GtkEventController--widget"><type>“widget”</type></link> was a construct-only
        property, so a <link linkend="GtkWidget"><type>GtkWidget</type></link> was provided whenever constructing a
        <link linkend="GtkEventController"><type>GtkEventController</type></link>. In GTK 4, <link linkend="GtkEventController--widget"><type>“widget”</type></link> is now
        read-only. Use <link linkend="gtk-widget-add-controller"><function>gtk_widget_add_controller()</function></link> to add an event
        controller to a widget.
      </para>
      <para>
        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. <link linkend="gtk-widget-add-controller"><function>gtk_widget_add_controller()</function></link> 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.
      </para>
      <para>
        Although not normally needed, an event controller could be
        removed from a widget in GTK 3 by destroying the event
        controller with <link linkend="g-object-unref"><function>g_object_unref()</function></link>. In GTK 4, you must use
        <link linkend="gtk-widget-remove-controller"><function>gtk_widget_remove_controller()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Focus handling changes</title>
      <para>
        The semantics of the <link linkend="GtkWidget--can-focus"><type>“can-focus”</type></link> 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 <link linkend="FALSE:CAPS"><literal>FALSE</literal></link>, the
        focus cannot enter the widget or any of its descendents, and the
        default value has changed from <link linkend="FALSE:CAPS"><literal>FALSE</literal></link> to <link linkend="TRUE:CAPS"><literal>TRUE</literal></link>. In addition,
        there is a <link linkend="GtkWidget--focusable"><type>“focusable”</type></link> property, which controls whether
        an individual widget can receive the input focus.
      </para>
      <para>
        The feature to automatically keep the focus widget scrolled into
        view with <link linkend="gtk-container-set-focus-vadjustment"><function>gtk_container_set_focus_vadjustment()</function></link> has been removed
        together with GtkContainer, and is provided by scrollable
        widgets instead. In the common case that the scrollable is a
        <link linkend="GtkViewport"><type>GtkViewport</type></link>, use <link linkend="GtkViewport--scroll-to-focus"><type>“scroll-to-focus”</type></link>.
      </para>
    </sect2>
    <sect2>
      <title>Use the new apis for keyboard shortcuts</title>
      <para>
        The APIs for keyboard shortcuts and accelerators have changed in
        GTK 4.
      </para>
      <para>
        Instead of GtkAccelGroup, you now use a <link linkend="GtkShortcutController"><type>GtkShortcutController</type></link>
        with global scope, and instead of GtkBindingSet, you now use
        <link linkend="gtk-widget-class-add-shortcut"><function>gtk_widget_class_add_shortcut()</function></link>, <link linkend="gtk-widget-class-add-binding"><function>gtk_widget_class_add_binding()</function></link>
        and its variants. In both cases, you probably want to add
        actions that can be triggered by your shortcuts.
      </para>
      <para>
        There is no direct replacement for loading and saving
        accelerators with GtkAccelMap. But since <link linkend="GtkShortcutController"><type>GtkShortcutController</type></link>
        implements <link linkend="GListModel"><type>GListModel</type></link> and both <link linkend="GtkShortcutTrigger"><type>GtkShortcutTrigger</type></link> and
        <link linkend="GtkShortcutAction"><type>GtkShortcutAction</type></link> can be serialized to strings, it is
        relatively easy to implement saving and loading yourself.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkEventBox</title>
      <para>
        GtkEventBox is no longer needed and has been removed. All
        widgets receive all events.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkButtonBox</title>
      <para>
        GtkButtonBox has been removed. Use a GtkBox instead.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkBox API changes</title>
      <para>
        The GtkBox pack-start and -end methods have been replaced by
        <link linkend="gtk-box-prepend"><function>gtk_box_prepend()</function></link> and <link linkend="gtk-box-append"><function>gtk_box_append()</function></link>. You can also reorder box
        children as necessary.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkWindow API changes</title>
      <para>
        Following the GdkSurface changes, a number of GtkWindow APIs
        that were X11-specific have been removed. This includes
        <link linkend="gtk-window-set-geometry-hints"><function>gtk_window_set_geometry_hints()</function></link>, <link linkend="gtk-window-set-gravity"><function>gtk_window_set_gravity()</function></link>,
        <link linkend="gtk-window-move"><function>gtk_window_move()</function></link>, <link linkend="gtk-window-parse-geometry"><function>gtk_window_parse_geometry()</function></link>,
        <link linkend="gtk-window-set-keep-above"><function>gtk_window_set_keep_above()</function></link>, <link linkend="gtk-window-set-keep-below"><function>gtk_window_set_keep_below()</function></link>,
        <link linkend="gtk-window-begin-resize-drag"><function>gtk_window_begin_resize_drag()</function></link>, <link linkend="gtk-window-begin-move-drag"><function>gtk_window_begin_move_drag()</function></link>.
        Most likely, you should just stop using them. In some cases, you
        can fall back to using the underlying <link linkend="GdkToplevel"><type>GdkToplevel</type></link> APIs (for
        example, <link linkend="gdk-toplevel-begin-resize"><function>gdk_toplevel_begin_resize()</function></link>).
      </para>
      <para>
        The APIs for controlling GtkWindow size have changed to be
        better aligned with the way size changes are integrated in the
        frame cycle. <link linkend="gtk-window-resize"><function>gtk_window_resize()</function></link> and <link linkend="gtk-window-get-size"><function>gtk_window_get_size()</function></link> have
        been removed. Instead, use <link linkend="gtk-window-set-default-size"><function>gtk_window_set_default_size()</function></link> and
        <link linkend="gtk-window-get-default-size"><function>gtk_window_get_default_size()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkHeaderBar and GtkActionBar API changes</title>
      <para>
        The <link linkend="gtk-header-bar-set-show-close-button"><function>gtk_header_bar_set_show_close_button()</function></link> function has been
        renamed to the more accurate name
        <link linkend="gtk-header-bar-set-show-title-buttons"><function>gtk_header_bar_set_show_title_buttons()</function></link>. The corresponding
        getter and the property itself have also been renamed. The
        default value of the property is now <link linkend="TRUE:CAPS"><literal>TRUE</literal></link> instead of <link linkend="FALSE:CAPS"><literal>FALSE</literal></link>.
      </para>
      <para>
        The <link linkend="gtk-header-bar-set-custom-title"><function>gtk_header_bar_set_custom_title()</function></link> function has been renamed
        to the more accurate name <link linkend="gtk-header-bar-set-title-widget"><function>gtk_header_bar_set_title_widget()</function></link>. The
        corresponding getter and the property itself have also been
        renamed.
      </para>
      <para>
        The <link linkend="gtk-header-bar-set-title"><function>gtk_header_bar_set_title()</function></link> function has been removed along
        with its corresponding getter and the property. By default
        <link linkend="GtkHeaderBar"><type>GtkHeaderBar</type></link> 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 <link linkend="GtkHeaderBar--title-widget"><type>“title-widget”</type></link> property to
        add a <link linkend="GtkLabel"><type>GtkLabel</type></link> as shown in the example in the <link linkend="GtkHeaderBar"><type>GtkHeaderBar</type></link>
        documentation.
      </para>
      <para>
        The <link linkend="gtk-header-bar-set-subtitle"><function>gtk_header_bar_set_subtitle()</function></link> function has been removed
        along with its corresponding getter and the property. The old
        <quote>subtitle</quote> behavior can be replicated by setting
        the <link linkend="GtkHeaderBar--title-widget"><type>“title-widget”</type></link> property to a <link linkend="GtkBox"><type>GtkBox</type></link> with two
        labels inside, with the title label matching the example in
        <link linkend="GtkHeaderBar"><type>GtkHeaderBar</type></link> documentation, and the subtitle label being
        similar, but with <quote>subtitle</quote> style class instead of
        <quote>title</quote>.
      </para>
      <para>
        The <link linkend="gtk-header-bar-set-has-subtitle"><function>gtk_header_bar_set_has_subtitle()</function></link> function has been removed
        along with its corresponding getter and the property. Its
        behavior can be replicated by setting the
        <link linkend="GtkHeaderBar--title-widget"><type>“title-widget”</type></link> property to a <link linkend="GtkStack"><type>GtkStack</type></link> with
        <link linkend="GtkStack--vhomogeneous"><type>“vhomogeneous”</type></link> property set to <link linkend="TRUE:CAPS"><literal>TRUE</literal></link> and two pages, each
        with a <link linkend="GtkBox"><type>GtkBox</type></link> with title and subtitle as described above.
      </para>
      <para>
        Some of the internal structure of <link linkend="GtkHeaderBar"><type>GtkHeaderBar</type></link> has been made
        available as public API: <link linkend="GtkWindowHandle"><type>GtkWindowHandle</type></link> and
        <link linkend="GtkWindowControls"><type>GtkWindowControls</type></link>. If you have unusual needs for custom
        headerbars, these might be useful to you.
      </para>
      <para>
        The ::pack-type child properties of GtkHeaderBar and
        GtkActionBar have been removed. If you need to programmatically
        place children, use the <link linkend="pack-start"><function>pack_start()</function></link> and <link linkend="pack-end"><function>pack_end()</function></link> APIs. In ui
        files, use the type attribute on the child element.
      </para>
      <para>
        gtk4-builder-tool can help with this conversion, with the –3to4
        option of the simplify command.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkStack, GtkAssistant and GtkNotebook API
      changes</title>
      <para>
        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.
      </para>
      <para>
        gtk4-builder-tool can help with this conversion, with the –3to4
        option of the simplify command.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to button class hierarchy changes</title>
      <para>
        <link linkend="GtkCheckButton"><type>GtkCheckButton</type></link> is no longer derived from <link linkend="GtkToggleButton"><type>GtkToggleButton</type></link>. Call
        <link linkend="gtk-check-button-set-active"><function>gtk_check_button_set_active()</function></link> instead of
        <link linkend="gtk-toggle-button-set-active"><function>gtk_toggle_button_set_active()</function></link>.
      </para>
      <para>
        <link linkend="GtkRadioButton"><type>GtkRadioButton</type></link> has been removed, and its grouping functionality
        has been added to <link linkend="GtkCheckButton"><type>GtkCheckButton</type></link> and <link linkend="GtkToggleButton"><type>GtkToggleButton</type></link>. 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 <link linkend="gtk-check-button-set-group"><function>gtk_check_button_set_group()</function></link> and
        <link linkend="gtk-toggle-button-set-group"><function>gtk_toggle_button_set_group()</function></link>.
      </para>
      <para>
        gtk4-builder-tool can help with this conversion, with the –3to4
        option of the simplify command.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkScrolledWindow API changes</title>
      <para>
        The constructor for GtkScrolledWindow no longer takes the
        adjustments as arguments - these were almost always <link linkend="NULL:CAPS"><literal>NULL</literal></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkBin removal</title>
      <para>
        The abstract base class GtkBin for single-child containers has
        been removed. The former subclasses are now derived directly
        from GtkWidget, and have a <quote>child</quote> property for
        their child widget. To add a child, use the setter for the
        <quote>child</quote> property (e.g. <link linkend="gtk-frame-set-child"><function>gtk_frame_set_child()</function></link>)
        instead of <link linkend="gtk-container-add"><function>gtk_container_add()</function></link>. Adding a child in a ui file with
        &lt;child&gt; still works.
      </para>
      <para>
        The affected classes are:
      </para>
      <itemizedlist spacing="compact">
        <listitem>
          <para>
            GtkAspectFrame
          </para>
        </listitem>
        <listitem>
          <para>
            GtkButton (and subclasses)
          </para>
        </listitem>
        <listitem>
          <para>
            GtkComboBox
          </para>
        </listitem>
        <listitem>
          <para>
            GtkFlowBoxChild
          </para>
        </listitem>
        <listitem>
          <para>
            GtkFrame
          </para>
        </listitem>
        <listitem>
          <para>
            GtkListBoxRow
          </para>
        </listitem>
        <listitem>
          <para>
            GtkOverlay
          </para>
        </listitem>
        <listitem>
          <para>
            GtkPopover
          </para>
        </listitem>
        <listitem>
          <para>
            GtkRevealer
          </para>
        </listitem>
        <listitem>
          <para>
            GtkScrolledWindow
          </para>
        </listitem>
        <listitem>
          <para>
            GtkSearchBar
          </para>
        </listitem>
        <listitem>
          <para>
            GtkViewport
          </para>
        </listitem>
        <listitem>
          <para>
            GtkWindow (and subclasses)
          </para>
        </listitem>
      </itemizedlist>
      <para>
        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 <link linkend="dispose"><function>dispose()</function></link> (to unparent your
        child), <link linkend="compute-expand"><function>compute_expand()</function></link> (if you want your container to
        propagate expand flags) and <link linkend="get-request-mode"><function>get_request_mode()</function></link> (if you want your
        container to support height-for-width.
      </para>
      <para>
        You may also want to implement the GtkBuildable interface, to
        support adding children with &lt;child&gt; in ui files.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkContainer removal</title>
      <para>
        The abstract base class GtkContainer for general containers has
        been removed. The former subclasses are now derived directly
        from GtkWidget, and have class-specific <link linkend="add"><function>add()</function></link> and <link linkend="remove"><function>remove()</function></link>
        functions. The most noticeable change is the use of
        <link linkend="gtk-box-append"><function>gtk_box_append()</function></link> or <link linkend="gtk-box-prepend"><function>gtk_box_prepend()</function></link> instead of
        <link linkend="gtk-container-add"><function>gtk_container_add()</function></link> for adding children to GtkBox, and the
        change to use container-specific remove functions, such as
        <link linkend="gtk-stack-remove"><function>gtk_stack_remove()</function></link> instead of <link linkend="gtk-container-remove"><function>gtk_container_remove()</function></link>. Adding a
        child in a ui file with &lt;child&gt; still works.
      </para>
      <para>
        The affected classes are:
      </para>
      <itemizedlist spacing="compact">
        <listitem>
          <para>
            GtkActionBar
          </para>
        </listitem>
        <listitem>
          <para>
            GtkBox (and subclasses)
          </para>
        </listitem>
        <listitem>
          <para>
            GtkExpander
          </para>
        </listitem>
        <listitem>
          <para>
            GtkFixed
          </para>
        </listitem>
        <listitem>
          <para>
            GtkFlowBox
          </para>
        </listitem>
        <listitem>
          <para>
            GtkGrid
          </para>
        </listitem>
        <listitem>
          <para>
            GtkHeaderBar
          </para>
        </listitem>
        <listitem>
          <para>
            GtkIconView
          </para>
        </listitem>
        <listitem>
          <para>
            GtkInfoBar
          </para>
        </listitem>
        <listitem>
          <para>
            GtkListBox
          </para>
        </listitem>
        <listitem>
          <para>
            GtkNotebook
          </para>
        </listitem>
        <listitem>
          <para>
            GtkPaned
          </para>
        </listitem>
        <listitem>
          <para>
            GtkStack
          </para>
        </listitem>
        <listitem>
          <para>
            GtkTextView
          </para>
        </listitem>
        <listitem>
          <para>
            GtkTreeView
          </para>
        </listitem>
      </itemizedlist>
      <para>
        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 <link linkend="GtkAssistantPage"><type>GtkAssistantPage</type></link>,
        <link linkend="GtkStackPage"><type>GtkStackPage</type></link> and the like.
      </para>
      <para>
        The replacements for <link linkend="gtk-container-add"><function>gtk_container_add()</function></link> are:
      </para>
      <informaltable>
        <tgroup cols="2">
          <colspec colwidth="35*" align="left" />
          <colspec colwidth="64*" align="left" />
          <thead>
            <row>
              <entry>
                Widget
              </entry>
              <entry>
                Replacement
              </entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>
                GtkActionBar
              </entry>
              <entry>
                <link linkend="gtk-action-bar-pack-start"><function>gtk_action_bar_pack_start()</function></link>, <link linkend="gtk-action-bar-pack-end"><function>gtk_action_bar_pack_end()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkBox
              </entry>
              <entry>
                <link linkend="gtk-box-prepend"><function>gtk_box_prepend()</function></link>, <link linkend="gtk-box-append"><function>gtk_box_append()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkExpander
              </entry>
              <entry>
                <link linkend="gtk-expander-set-child"><function>gtk_expander_set_child()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkFixed
              </entry>
              <entry>
                <link linkend="gtk-fixed-put"><function>gtk_fixed_put()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkFlowBox
              </entry>
              <entry>
                <link linkend="gtk-flow-box-insert"><function>gtk_flow_box_insert()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkGrid
              </entry>
              <entry>
                <link linkend="gtk-grid-attach"><function>gtk_grid_attach()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkHeaderBar
              </entry>
              <entry>
                <link linkend="gtk-header-bar-pack-start"><function>gtk_header_bar_pack_start()</function></link>, <link linkend="gtk-header-bar-pack-end"><function>gtk_header_bar_pack_end()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkIconView
              </entry>
              <entry>
                -
              </entry>
            </row>
            <row>
              <entry>
                GtkInfoBar
              </entry>
              <entry>
                <link linkend="gtk-info-bar-add-child"><function>gtk_info_bar_add_child()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkListBox
              </entry>
              <entry>
                <link linkend="gtk-list-box-insert"><function>gtk_list_box_insert()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkNotebook
              </entry>
              <entry>
                <link linkend="gtk-notebook-append-page"><function>gtk_notebook_append_page()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkPaned
              </entry>
              <entry>
                <link linkend="gtk-paned-set-start-child"><function>gtk_paned_set_start_child()</function></link>, <link linkend="gtk-paned-set-end-child"><function>gtk_paned_set_end_child()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkStack
              </entry>
              <entry>
                <link linkend="gtk-stack-add-child"><function>gtk_stack_add_child()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkTextView
              </entry>
              <entry>
                <link linkend="gtk-text-view-add-child-at-anchor"><function>gtk_text_view_add_child_at_anchor()</function></link>,
                <link linkend="gtk-text-view-add-overlay"><function>gtk_text_view_add_overlay()</function></link>
              </entry>
            </row>
            <row>
              <entry>
                GtkTreeView
              </entry>
              <entry>
                -
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
    </sect2>
    <sect2>
      <title>Stop using GtkContainer::border-width</title>
      <para>
        GTK 4 has removed the <link linkend="GtkContainer-border-width"><type>“border-width”</type></link> 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.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to <link linkend="gtk-widget-destroy"><function>gtk_widget_destroy()</function></link> removal</title>
      <para>
        The function <link linkend="gtk-widget-destroy"><function>gtk_widget_destroy()</function></link> has been removed. To
        explicitly destroy a toplevel window, use <link linkend="gtk-window-destroy"><function>gtk_window_destroy()</function></link>.
        To destroy a widget that is part of a hierarchy, remove it from
        its parent using a container-specific remove API, such as
        <link linkend="gtk-box-remove"><function>gtk_box_remove()</function></link> or <link linkend="gtk-stack-remove"><function>gtk_stack_remove()</function></link>. To destroy a
        freestanding non-toplevel widget, use <link linkend="g-object-unref"><function>g_object_unref()</function></link> to drop
        your reference.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to coordinate API changes</title>
      <para>
        A number of APIs that are accepting or returning coordinates
        have been changed from ints to doubles:
        <link linkend="gtk-widget-translate-coordinates"><function>gtk_widget_translate_coordinates()</function></link>, <link linkend="gtk-fixed-put"><function>gtk_fixed_put()</function></link>,
        <link linkend="gtk-fixed-move"><function>gtk_fixed_move()</function></link>. This change is mostly transparent, except for
        cases where out parameters are involved: you need to pass
        double* now, instead of int*.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkStyleContext API changes</title>
      <para>
        The getters in the GtkStyleContext API, such as
        <link linkend="gtk-style-context-get-property"><function>gtk_style_context_get_property()</function></link>, <link linkend="gtk-style-context-get"><function>gtk_style_context_get()</function></link>, or
        <link linkend="gtk-style-context-get-color"><function>gtk_style_context_get_color()</function></link> have lost their state argument,
        and always use the context’s current state. Update all callers
        to omit the state argument.
      </para>
      <para>
        The most commonly used GtkStyleContext API,
        <link linkend="gtk-style-context-add-class"><function>gtk_style_context_add_class()</function></link>, has been moved to GtkWidget as
        <link linkend="gtk-widget-add-css-class"><function>gtk_widget_add_css_class()</function></link>, as have the corresponding
        <link linkend="gtk-style-context-remove-class"><function>gtk_style_context_remove_class()</function></link> and
        <link linkend="gtk-style-context-has-class"><function>gtk_style_context_has_class()</function></link> APIs.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkCssProvider API changes</title>
      <para>
        In GTK 4, the various <link linkend="GtkCssProvider"><type>GtkCssProvider</type></link> load functions have lost
        their <link linkend="GError"><type>GError</type></link> argument. If you want to handle CSS loading
        errors, use the <link linkend="GtkCssProvider-parsing-error"><type>“parsing-error”</type></link> signal instead.
        <link linkend="gtk-css-provider-get-named"><function>gtk_css_provider_get_named()</function></link> has been replaced by
        <link linkend="gtk-css-provider-load-named"><function>gtk_css_provider_load_named()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkShadowType and GtkRelief properties</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkWidget’s size request changes</title>
      <para>
        GTK 3 used five different virtual functions in GtkWidget to
        implement size requisition, namely the
        <link linkend="gtk-widget-get-preferred-width"><function>gtk_widget_get_preferred_width()</function></link> family of functions. To
        simplify widget implementations, GTK 4 uses only one virtual
        function, GtkWidgetClass::<link linkend="measure"><function>measure()</function></link> that widgets have to
        implement. <link linkend="gtk-widget-measure"><function>gtk_widget_measure()</function></link> replaces the various
        gtk_widget_get_preferred_ functions for querying sizes.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkWidget’s size allocation changes</title>
      <para>
        The <link linkend="GtkWidget.size-allocate"><function>GtkWidget.size_allocate()</function></link> vfunc takes the baseline as an
        argument now, so you no longer need to call
        <link linkend="gtk-widget-get-allocated-baseline"><function>gtk_widget_get_allocated_baseline()</function></link> to get it.
      </para>
      <para>
        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 <link linkend="GtkDrawingArea-resize"><type>“resize”</type></link> or
        <link linkend="GtkGLArea-resize"><type>“resize”</type></link> signals. If you want to track the size of
        toplevel windows, use property notification for
        <link linkend="GtkWindow--default-width"><type>“default-width”</type></link> and <link linkend="GtkWindow--default-height"><type>“default-height”</type></link>.
      </para>
    </sect2>
    <sect2>
      <title>Switch to GtkWidget’s children APIs</title>
      <para>
        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: <link linkend="gtk-widget-get-first-child"><function>gtk_widget_get_first_child()</function></link>,
        <link linkend="gtk-widget-get-last-child"><function>gtk_widget_get_last_child()</function></link>, <link linkend="gtk-widget-get-next-sibling"><function>gtk_widget_get_next_sibling()</function></link>,
        <link linkend="gtk-widget-get-prev-sibling"><function>gtk_widget_get_prev_sibling()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Don’t use -gtk-gradient in your CSS</title>
      <para>
        GTK now supports standard CSS syntax for both linear and radial
        gradients, just use those.
      </para>
    </sect2>
    <sect2>
      <title>Don’t use -gtk-icon-effect in your CSS</title>
      <para>
        GTK now supports a more versatile -gtk-icon-filter instead.
      </para>
      <para>
        Replace
      </para>
      <informaltable>
        <tgroup cols="2">
          <colspec align="left" />
          <colspec align="left" />
          <thead>
            <row>
              <entry>
                Old
              </entry>
              <entry>
                Replacement
              </entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>
                -gtk-icon-effect: dim
              </entry>
              <entry>
                -gtk-icon-filter: opacity(0.5)
              </entry>
            </row>
            <row>
              <entry>
                -gtk-icon-effect: highlight
              </entry>
              <entry>
                -gtk-icon-filter: brightness(1.2)
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
    </sect2>
    <sect2>
      <title>Don’t use -gtk-icon-theme in your CSS</title>
      <para>
        GTK 4 always uses the current icon theme, with no way to change
        this.
      </para>
    </sect2>
    <sect2>
      <title>Don’t use -gtk-outline-…-radius in your CSS</title>
      <para>
        These non-standard properties have been removed from GTK CSS.
        Just use regular border radius.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to drawing model changes</title>
      <para>
        This area has seen the most radical changes in the transition
        from GTK 3 to GTK 4. Widgets no longer use a <link linkend="draw"><function>draw()</function></link> function to
        render their contents to a cairo surface. Instead, they have a
        <link linkend="snapshot"><function>snapshot()</function></link> function that creates one or more GskRenderNodes to
        represent their content. Third-party widgets that use a <link linkend="draw"><function>draw()</function></link>
        function or a <link linkend="GtkWidget-draw"><type>“draw”</type></link> signal handler for custom drawing
        will need to be converted to use <link linkend="gtk-snapshot-append-cairo"><function>gtk_snapshot_append_cairo()</function></link>.
      </para>
      <para>
        The auxiliary <link linkend="GtkSnapshot"><type>GtkSnapshot</type></link> object has APIs to help with creating
        render nodes.
      </para>
      <para>
        If you are using a <link linkend="GtkDrawingArea"><type>GtkDrawingArea</type></link> for custom drawing, you need
        to switch to using <link linkend="gtk-drawing-area-set-draw-func"><function>gtk_drawing_area_set_draw_func()</function></link> to set a
        draw function instead of connecting a handler to the
        <link linkend="GtkWidget-draw"><type>“draw”</type></link> signal.
      </para>
    </sect2>
    <sect2>
      <title>Stop using APIs to query GdkSurfaces</title>
      <para>
        A number of APIs for querying special-purpose windows have been
        removed, since these windows are no longer publicly available:
        <link linkend="gtk-tree-view-get-bin-window"><function>gtk_tree_view_get_bin_window()</function></link>, <link linkend="gtk-viewport-get-bin-window"><function>gtk_viewport_get_bin_window()</function></link>,
        <link linkend="gtk-viewport-get-view-window"><function>gtk_viewport_get_view_window()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Widgets are now visible by default</title>
      <para>
        The default value of <link linkend="GtkWidget--visible"><type>“visible”</type></link> in GTK 4 is <link linkend="TRUE:CAPS"><literal>TRUE</literal></link>, 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.
      </para>
      <para>
        A convenient way to remove unnecessary property assignments like
        this from ui files it run the command
        <literal>gtk4-builder-tool simplify --replace</literal> on them.
      </para>
      <para>
        The function <link linkend="gtk-widget-show-all"><function>gtk_widget_show_all()</function></link>, the <link linkend="GtkWidget--no-show-all"><type>“no-show-all”</type></link>
        property and its getter and setter have been removed in GTK 4,
        so you should stop using them.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changes in animated hiding and showing of
      widgets</title>
      <para>
        Widgets that appear and disappear with an animation, such as
        GtkPopover, GtkInfoBar, GtkRevealer no longer use
        <link linkend="gtk-widget-show"><function>gtk_widget_show()</function></link> and <link linkend="gtk-widget-hide"><function>gtk_widget_hide()</function></link> for this, but have
        gained dedicated APIs for this purpose that you should use
        instead.
      </para>
    </sect2>
    <sect2>
      <title>Stop passing commandline arguments to gtk_init</title>
      <para>
        The <link linkend="gtk-init"><function>gtk_init()</function></link> and <link linkend="gtk-init-check"><function>gtk_init_check()</function></link> functions no longer accept
        commandline arguments. Just call them without arguments. Other
        initialization functions that were purely related to commandline
        argument handling, such as <link linkend="gtk-parse-args"><function>gtk_parse_args()</function></link> and
        <link linkend="gtk-get-option-group"><function>gtk_get_option_group()</function></link>, are gone.
      </para>
      <para>
        The APIs to initialize GDK separately are also gone, but it is
        very unlikely that you are affected by that.
      </para>
    </sect2>
    <sect2>
      <title>GdkPixbuf is deemphasized</title>
      <para>
        A number of <link linkend="GdkPixbuf-based"><type>GdkPixbuf-based</type></link> APIs have been removed. The
        available replacements are either using <link linkend="GIcon"><type>GIcon</type></link>, or the newly
        introduced <link linkend="GdkTexture"><type>GdkTexture</type></link> or <link linkend="GdkPaintable"><type>GdkPaintable</type></link> classes instead. If you
        are dealing with pixbufs, you can use
        <link linkend="gdk-texture-new-for-pixbuf"><function>gdk_texture_new_for_pixbuf()</function></link> to convert them to texture objects
        where needed.
      </para>
    </sect2>
    <sect2>
      <title>GtkWidget event signals are removed</title>
      <para>
        Event controllers and <link linkend="GtkGestures"><type>GtkGestures</type></link> 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
        <link linkend="GtkWidget-motion-event"><type>“motion-event”</type></link> or <link linkend="GtkWidget-event"><type>“event”</type></link> have been removed.
        All event handling is done via event controllers now.
      </para>
    </sect2>
    <sect2>
      <title>Invalidation handling has changed</title>
      <para>
        Only <link linkend="gtk-widget-queue-draw"><function>gtk_widget_queue_draw()</function></link> is left to mark a widget as needing
        redraw. Variations like <link linkend="gtk-widget-queue-draw-rectangle"><function>gtk_widget_queue_draw_rectangle()</function></link> or
        <link linkend="gtk-widget-queue-draw-region"><function>gtk_widget_queue_draw_region()</function></link> are no longer available.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkWidget::draw</title>
      <para>
        The <link linkend="GtkWidget-draw"><type>“draw”</type></link> signal has been removed. Widgets need to
        implement the <link linkend="GtkWidgetClass.snapshot"><function>GtkWidgetClass.snapshot()</function></link> function now.
        Connecting draw signal handlers is no longer possible. If you
        want to keep using cairo for drawing, use
        <link linkend="gtk-snaphot-append-cairo"><function>gtk_snaphot_append_cairo()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Window content observation has changed</title>
      <para>
        Observing widget contents and widget size is now done by using
        the <link linkend="GtkWidgetPaintable"><type>GtkWidgetPaintable</type></link> object instead of connecting to widget
        signals.
      </para>
    </sect2>
    <sect2>
      <title>Monitor handling has changed</title>
      <para>
        Instead of a monitor number, <link linkend="GdkMonitor"><type>GdkMonitor</type></link> is now used throughout.
        <link linkend="gdk-display-get-monitors"><function>gdk_display_get_monitors()</function></link> returns the list of monitors that can
        be queried or observed for monitors to pass to APIs like
        <link linkend="gtk-window-fullscreen-on-monitor"><function>gtk_window_fullscreen_on_monitor()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to monitor API changes</title>
      <para>
        The <link linkend="gdk-monitor-get-workarea"><function>gdk_monitor_get_workarea()</function></link> API is gone. Individual backends
        can still provide this information, for example with
        <link linkend="gdk-x11-monitor-get-workarea"><function>gdk_x11_monitor_get_workarea()</function></link>.
      </para>
      <para>
        If you use this information, your code should check which
        backend is in use and then call the appropriate backend API.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to cursor API changes</title>
      <para>
        Use the new <link linkend="gtk-widget-set-cursor"><function>gtk_widget_set_cursor()</function></link> 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.
      </para>
      <para>
        For creating standard cursors, <link linkend="gdk-cursor-new-for-display"><function>gdk_cursor_new_for_display()</function></link> has
        been removed, you have to use cursor names instead of
        GdkCursorType. For creating custom cursors, use
        <link linkend="gdk-cursor-new-from-texture"><function>gdk_cursor_new_from_texture()</function></link>. The ability to get cursor images
        has been removed.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to icon size API changes</title>
      <para>
        Instead of the existing extensible set of symbolic icon sizes,
        GTK now only supports normal and large icons with the
        <link linkend="GtkIconSize"><type>GtkIconSize</type></link> enumeration. The actual sizes can be defined by
        themes via the CSS property -gtk-icon-size.
      </para>
      <para>
        GtkImage setters like <link linkend="gtk-image-set-from-icon-name"><function>gtk_image_set_from_icon_name()</function></link> no longer
        take a <link linkend="GtkIconSize"><type>GtkIconSize</type></link> argument. You can use the separate
        <link linkend="gtk-image-set-icon-size"><function>gtk_image_set_icon_size()</function></link> setter if you need to override the
        icon size.
      </para>
      <para>
        The :stock-size property of GtkCellRendererPixbuf has been
        renamed to <link linkend="GtkCellRendererPixbuf--icon-size"><type>“icon-size”</type></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changes in the GtkAssistant API</title>
      <para>
        The :has-padding property is gone, and GtkAssistant no longer
        adds padding to pages. You can easily do that yourself.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changes in the API of GtkEntry, GtkSearchEntry and
      GtkSpinButton</title>
      <para>
        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
        <link linkend="gtk-entry-grab-focus-without-selecting"><function>gtk_entry_grab_focus_without_selecting()</function></link> on a search entry.
      </para>
      <para>
        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, <link linkend="gtk-spin-button-set-max-width-chars"><function>gtk_spin_button_set_max_width_chars()</function></link> has been removed
        in favor of <link linkend="gtk-editable-set-max-width-chars"><function>gtk_editable_set_max_width_chars()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changes in GtkOverlay API</title>
      <para>
        The GtkOverlay :pass-through child property has been replaced by
        the <link linkend="GtkWidget--can-target"><type>“can-target”</type></link> property. Note that they have the
        opposite sense: pass-through == !can-target.
      </para>
    </sect2>
    <sect2>
      <title>Use GtkFixed instead of GtkLayout</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to search entry changes</title>
      <para>
        The way search entries are connected to global events has
        changed; <link linkend="gtk-search-entry-handle-event"><function>gtk_search_entry_handle_event()</function></link> has been dropped and
        replaced by <link linkend="gtk-search-entry-set-key-capture-widget"><function>gtk_search_entry_set_key_capture_widget()</function></link> and
        <link linkend="gtk-event-controller-key-forward"><function>gtk_event_controller_key_forward()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkScale changes</title>
      <para>
        The default value of <link linkend="GtkScale--draw-value"><type>“draw-value”</type></link> has been changed to
        <link linkend="FALSE:CAPS"><literal>FALSE</literal></link>. If you want your scales to draw values, you will have to
        set this property explicitly now.
      </para>
      <para>
        gtk4-builder-tool can help with this conversion, with the –3to4
        option of the simplify command.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <link linkend="gtk-window-activate-default"><function>gtk_window_activate_default()</function></link></title>
      <para>
        The handling of default widgets has been changed, and activating
        the default now works by calling <link linkend="gtk-widget-activate-default"><function>gtk_widget_activate_default()</function></link>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Stop using <link linkend="gtk-widget-grab-default"><function>gtk_widget_grab_default()</function></link></title>
      <para>
        The function <link linkend="gtk-widget-grab-default"><function>gtk_widget_grab_default()</function></link> has been removed. If you
        need to mark a widget as default, use
        <link linkend="gtk-window-set-default-widget"><function>gtk_window_set_default_widget()</function></link> directly.
      </para>
    </sect2>
    <sect2>
      <title>Stop setting ::has-default and ::has-focus in .ui
      files</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Stop using the GtkWidget::display-changed signal</title>
      <para>
        To track the current display, use the <link linkend="GtkWidget-root"><type>“root”</type></link> property
        instead.
      </para>
    </sect2>
    <sect2>
      <title>GtkPopover::modal has been renamed to autohide</title>
      <para>
        The modal property has been renamed to autohide.
        gtk-builder-tool can assist with the rename in ui files.
      </para>
    </sect2>
    <sect2>
      <title>gtk_widget_get_surface has been removed</title>
      <para>
        <link linkend="gtk-widget-get-surface"><function>gtk_widget_get_surface()</function></link> has been removed. Use
        <link linkend="gtk-native-get-surface"><function>gtk_native_get_surface()</function></link> in combination with
        <link linkend="gtk-widget-get-native"><function>gtk_widget_get_native()</function></link> instead.
      </para>
    </sect2>
    <sect2>
      <title>gtk_widget_is_toplevel has been removed</title>
      <para>
        <link linkend="gtk-widget-is-toplevel"><function>gtk_widget_is_toplevel()</function></link> has been removed. Use GTK_IS_ROOT,
        GTK_IS_NATIVE or GTK_IS_WINDOW instead, as appropriate.
      </para>
    </sect2>
    <sect2>
      <title>gtk_widget_get_toplevel has been removed</title>
      <para>
        <link linkend="gtk-widget-get-toplevel"><function>gtk_widget_get_toplevel()</function></link> has been removed. Use
        <link linkend="gtk-widget-get-root"><function>gtk_widget_get_root()</function></link> or <link linkend="gtk-widget-get-native"><function>gtk_widget_get_native()</function></link> instead, as
        appropriate.
      </para>
    </sect2>
    <sect2>
      <title>GtkEntryBuffer ::deleted-text has changed</title>
      <para>
        To allow signal handlers to access the deleted text before it
        has been deleted <link linkend="GtkEntryBuffer-deleted-text"><type>“deleted-text”</type></link> has changed from
        <link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> to <link linkend="G-SIGNAL-RUN-LAST:CAPS"><literal>G_SIGNAL_RUN_LAST</literal></link>. The default handler
        removes the text from the <link linkend="GtkEntryBuffer"><type>GtkEntryBuffer</type></link>.
      </para>
      <para>
        To adapt existing code, use <link linkend="g-signal-connect-after"><function>g_signal_connect_after()</function></link> or
        <link linkend="G-CONNECT-AFTER:CAPS"><literal>G_CONNECT_AFTER</literal></link> when using <link linkend="g-signal-connect-data"><function>g_signal_connect_data()</function></link> or
        <link linkend="g-signal-connect-object"><function>g_signal_connect_object()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>GtkMenu, GtkMenuBar and GtkMenuItem are gone</title>
      <para>
        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.
      </para>
      <para>
        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.
      </para>
      <para>
        Tabular menus were rarely used and complicated the menu code, so
        they have not been brought over to <link linkend="GtkPopoverMenu"><type>GtkPopoverMenu</type></link>. If you need
        complex layout in menu-like popups, consider directly using a
        <link linkend="GtkPopover"><type>GtkPopover</type></link> instead.
      </para>
      <para>
        Since menus are gone, GtkMenuButton also lost its ability to
        show menus, and needs to be used with popovers in GTK 4.
      </para>
    </sect2>
    <sect2>
      <title>GtkToolbar has been removed</title>
      <para>
        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 <quote>toolbar</quote>
        style class.
      </para>
    </sect2>
    <sect2>
      <title>GtkAspectFrame is no longer a frame</title>
      <para>
        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.
      </para>
    </sect2>
    <sect2>
      <title>Stop using custom tooltip windows</title>
      <para>
        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 <link linkend="gtk-tooltip-set-custom"><function>gtk_tooltip_set_custom()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Switch to the new Drag-and-Drop api</title>
      <para>
        The source-side Drag-and-Drop apis in GTK 4 have been changed to
        use an event controller, <link linkend="GtkDragSource"><type>GtkDragSource</type></link>. Instead of calling
        <link linkend="gtk-drag-source-set"><function>gtk_drag_source_set()</function></link> and connecting to <link linkend="GtkWidget"><type>GtkWidget</type></link> signals, you
        create a <link linkend="GtkDragSource"><type>GtkDragSource</type></link> object, attach it to the widget with
        <link linkend="gtk-widget-add-controller"><function>gtk_widget_add_controller()</function></link>, and connect to <link linkend="GtkDragSource"><type>GtkDragSource</type></link>
        signals. Instead of calling <link linkend="gtk-drag-begin"><function>gtk_drag_begin()</function></link> on a widget to
        start a drag manually, call <link linkend="gdk-drag-begin"><function>gdk_drag_begin()</function></link>. The
        ::drag-data-get signal has been replaced by the
        <link linkend="GtkDragSource-prepare"><type>“prepare”</type></link> signal, which returns a
        <link linkend="GdkContentProvider"><type>GdkContentProvider</type></link> for the drag operation.
      </para>
      <para>
        The destination-side Drag-and-Drop API in GTK 4 have also been
        changed to use an event controller, <link linkend="GtkDropTarget"><type>GtkDropTarget</type></link>. Instead of
        calling <link linkend="gtk-drag-dest-set"><function>gtk_drag_dest_set()</function></link> and connecting to <link linkend="GtkWidget"><type>GtkWidget</type></link>
        signals, you create a <link linkend="GtkDropTarget"><type>GtkDropTarget</type></link> object, attach it to the
        widget with <link linkend="gtk-widget-add-controller"><function>gtk_widget_add_controller()</function></link>, and connect to
        <link linkend="GtkDropTarget"><type>GtkDropTarget</type></link> signals. The ::drag-motion signal has been
        renamed to <link linkend="GtkDropTarget-accept"><type>“accept”</type></link>, and instead of
        ::drag-data-received, you need to use async read methods on the
        <link linkend="GdkDrop"><type>GdkDrop</type></link> object, such as <link linkend="gdk-drop-read-async"><function>gdk_drop_read_async()</function></link> or
        <link linkend="gdk-drop-read-value-async"><function>gdk_drop_read_value_async()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkIconTheme API changes</title>
      <para>
        <link linkend="gtk-icon-theme-lookup-icon"><function>gtk_icon_theme_lookup_icon()</function></link> returns a <link linkend="GtkIconPaintable"><type>GtkIconPaintable</type></link> object
        now, instead of a <link linkend="GtkIconInfo"><type>GtkIconInfo</type></link>. 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.
      </para>
      <para>
        Note that while GTK 4 is moving towards <link linkend="GdkPaintable"><type>GdkPaintable</type></link> as a
        primary API for paintable content, it is meant to be a
        <quote>pure</quote> content producer, therefore a
        <link linkend="GtkIconPaintable"><type>GtkIconPaintable</type></link> for a symbolic icon will
        <emphasis>not</emphasis> get recolored depending on the context
        it is rendered it. To properly render a symbolic icon that is
        provided in the form of a <link linkend="GtkIconPaintable"><type>GtkIconPaintable</type></link> (this can be checked
        with <link linkend="gtk-icon-paintable-is-symbolic"><function>gtk_icon_paintable_is_symbolic()</function></link>), you have to call
        <link linkend="gtk-icon-paintable-get-icon-name"><function>gtk_icon_paintable_get_icon_name()</function></link> and set the icon name on a
        <link linkend="GtkImage"><type>GtkImage</type></link>.
      </para>
    </sect2>
    <sect2>
      <title>Update to GtkFileChooser API changes</title>
      <para>
        GtkFileChooser moved to a GFile-based API. If you need to
        convert a path or a URI, use <link linkend="g-file-new-for-path"><function>g_file_new_for_path()</function></link>,
        <link linkend="g-file-new-for-commandline-arg"><function>g_file_new_for_commandline_arg()</function></link>, or <link linkend="g-file-new-for-uri"><function>g_file_new_for_uri()</function></link>;
        similarly, if you need to get a path, name or URI from a GFile,
        use <link linkend="g-file-get-path"><function>g_file_get_path()</function></link>, <link linkend="g-file-get-basename"><function>g_file_get_basename()</function></link> or
        <link linkend="g-file-get-uri"><function>g_file_get_uri()</function></link>. With the removal or path and URI-based
        functions, the <quote>local-only</quote> property has been
        removed; GFile can be used to access non-local as well as local
        resources.
      </para>
      <para>
        The GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER action has been
        removed. Use <link linkend="GTK-FILE-CHOOSER-ACTION-SELECT-FOLDER:CAPS"><literal>GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</literal></link>, instead. If
        a new folder is needed, the user can create one.
      </para>
      <para>
        The <quote>confirm-overwrite</quote> signal, and the
        <quote>do-overwrite-confirmation</quote> 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.
      </para>
      <para>
        GtkFileChooser does not support a custom extra widget any more.
        If you need to add extra widgets, use
        <link linkend="gtk-file-chooser-add-choice"><function>gtk_file_chooser_add_choice()</function></link> instead.
      </para>
      <para>
        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
        <link linkend="GtkFileChooser-selection-changed"><type>“selection-changed”</type></link> signal is emitted.
      </para>
    </sect2>
    <sect2>
      <title>Stop using blocking dialog functions</title>
      <para>
        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, <quote>stop-the-world</quote>
        functions do not fit the event-driven programming model of GTK.
      </para>
      <para>
        You can replace calls to <link linkend="gtk-dialog-run"><function>gtk_dialog_run()</function></link> by specifying that the
        <link linkend="GtkDialog"><type>GtkDialog</type></link> must be modal using <link linkend="gtk-window-set-modal"><function>gtk_window_set_modal()</function></link> or the
        <link linkend="GTK-DIALOG-MODAL:CAPS"><literal>GTK_DIALOG_MODAL</literal></link> flag, and connecting to the
        <link linkend="GtkDialog-response"><type>“response”</type></link> signal.
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkBuildable API</title>
      <para>
        All the GtkBuildable API was made private, except for the getter
        function to retrieve the buildable ID. If you are using
        <link linkend="gtk-buildable-get-name"><function>gtk_buildable_get_name()</function></link> you should replace it with
        <link linkend="gtk-buildable-get-buildable-id"><function>gtk_buildable_get_buildable_id()</function></link>.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkAboutDialog API changes</title>
      <para>
        GtkAboutDialog now directly derives from GtkWindow, the
        GtkDialog API can no longer be used on it.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to GtkTreeView and GtkIconView tooltip context
      changes</title>
      <para>
        The getter functions for retrieving the data from <link linkend="GtkTreeView"><type>GtkTreeView</type></link>
        and <link linkend="GtkIconView"><type>GtkIconView</type></link> inside a <link linkend="GtkWidget-query-tooltip"><type>“query-tooltip”</type></link> signal do
        not take the pointer coordinates as inout arguments any more,
        but as normal in ones.
      </para>
      <para>
        See: <link linkend="gtk-tree-view-get-tooltip-context"><function>gtk_tree_view_get_tooltip_context()</function></link>,
        <link linkend="gtk-icon-view-get-tooltip-context"><function>gtk_icon_view_get_tooltip_context()</function></link>
      </para>
    </sect2>
    <sect2>
      <title>Stop using GtkFileChooserButton</title>
      <para>
        The <literal>GtkFileChooserButton</literal> widget was removed,
        due to its shortcomings in the user interaction. You can replace
        it with a simple <link linkend="GtkButton"><type>GtkButton</type></link> that shows a <link linkend="GtkFileChooserNative"><type>GtkFileChooserNative</type></link>
        dialog when clicked; once the file selection has completed, you
        can update the label of the <link linkend="GtkButton"><type>GtkButton</type></link> with the selected file.
      </para>
    </sect2>
    <sect2>
      <title>Adapt to changed GtkSettings properties</title>
      <para>
        In GTK 3 the <link linkend="GtkSettings--gtk-cursor-aspect-ratio"><type>“gtk-cursor-aspect-ratio”</type></link> property of
        <link linkend="GtkSettings"><type>GtkSettings</type></link> was a float. In GTK 4 this has been changed to a
        double.
      </para>
    </sect2>
  </sect1>
  <sect1>
    <title>Changes to consider after the switch</title>
    <para>
      GTK 4 has a number of new features that you may want to take
      advantage of once the dust has settled over the initial migration.
    </para>
    <sect2>
      <title>Consider porting to the new list widgets</title>
      <para>
        In GTK 2 and 3, GtkTreeModel and GtkCellRenderer and widgets
        using these were the primary way of displaying data and lists.
        GTK 4 brings a new family of widgets for this purpose that uses
        list models instead of tree models, and widgets instead of cell
        renderers.
      </para>
      <para>
        To learn more about the new list widgets, you can read the
        <link linkend="ListWidget">List Widget Overview</link>.
      </para>
    </sect2>
  </sect1>
</chapter>
