GTK4 gtk_window_destroy()

I had just a look on GTK4 gtk_window_destroy() – as the handling of GtkWindows for language bindings is a bit special, they are not contained in other containers, we discussed that recently.

/**
 * gtk_window_destroy:
 * @window: The window to destroy
 *
 * Drop the internal reference GTK holds on toplevel windows.
 */
void
gtk_window_destroy (GtkWindow *window)
{
  guint i;

  g_return_if_fail (GTK_IS_WINDOW (window));

  /* If gtk_window_destroy() has been called before. Can happen
   * when destroying a dialog manually in a ::close handler for example. */
  if (!g_list_store_find (toplevel_list, window, &i))
    return;

  g_object_ref (window);
  gtk_tooltip_unset_surface (GTK_NATIVE (window));

  g_list_store_remove (toplevel_list, i);

  gtk_window_hide (GTK_WIDGET (window));
  gtk_widget_unrealize (GTK_WIDGET (window));

  g_object_unref (window);
}

First, gtk_window_hide (GTK_WIDGET (window)); is a bit strange, we cast to Widget and call a windows method?

But what I was wondering about is where the window is really deallocated, where the memory is freed? Because there is only a ref/unref pair, I would expect an additional g_object_unref (window); which may then free the window when ref count drops to zero?

And maybe another question:

/**
 * gtk_window_new:
 * 
 * Creates a new #GtkWindow, which is a toplevel window that can
 * contain other widgets.
 *
 * To get an undecorated window (no window borders), use
 * gtk_window_set_decorated().
 *
 * All top-level windows created by gtk_window_new() are stored in
 * an internal top-level window list.  This list can be obtained from
 * gtk_window_list_toplevels().  Due to Gtk+ keeping a reference to
 * the window internally, gtk_window_new() does not return a reference
 * to the caller.
 *
 * To delete a #GtkWindow, call gtk_window_destroy().
 * 
 * Returns: a new #GtkWindow.
 **/
GtkWidget*
gtk_window_new (void)
{
  return g_object_new (GTK_TYPE_WINDOW, NULL);
}

From my understanding gtk_window_new() returns a non floating widget with ref count set to 1. But where does the storing in the internal top-level window list take place?

Hi,

I’m not expert here but you might find some insight in the discussion on the issue #2707. As everything in Gtk4 is a widget I expect memory allocation and clean up happen in widget_class_init and wiget_dispose.
This perhaps explain the cast of the window to a widget.

1 Like

The g_list_store_remove() call unrefs the window.

in gtk_window_constructed():

static void
gtk_window_constructed (GObject *object)
{
  GtkWindow *window = GTK_WINDOW (object);
  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);

  G_OBJECT_CLASS (gtk_window_parent_class)->constructed (object);

  priv->click_gesture = gtk_gesture_click_new ();
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->click_gesture), 0);
  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->click_gesture),
                                              GTK_PHASE_BUBBLE);
  g_signal_connect (priv->click_gesture, "pressed",
                    G_CALLBACK (click_gesture_pressed_cb), object);
  gtk_widget_add_controller (GTK_WIDGET (object), GTK_EVENT_CONTROLLER (priv->click_gesture));

  g_list_store_append (toplevel_list, window); /* <-- */
  g_object_unref (window);
}
1 Like