When is GtkTextView's preferred size updated?

130 Views Asked by At

I have noticed that GtkTextView's preferred size doesn't change immediately after its contents are changed, but only sometime later in event processing.

In following example, when you click the button, the text in GtkTextView is updated via gtk_text_buffer_set_text(). The new text is long enough to cause a line wrap, and so the preferred height of the control should change. But the gtk_widget_get_preferred_size() still reports old preferred height. Later, in 'size-allocate' event handler, the gtk_widget_get_preferred_size() is already reporting correct size for new contents.

I am trying to understand what happens between the return from button's 'clicked' event handler and 'size-allocate' event handler, that causes GtkTextView's preferred size to update to reflect its changed contents.

#include <gtk/gtk.h>

static bool button_clicked(GtkWidget* obj, GtkWidget* view)
{
  // set text in GtkTextView to
  const char* long_text="aaaaa aaaaa aaaaa aaaaa aaaaa aaaaa aaaaa";
  printf("----------------------------\n");
  printf("in button_clicked(): setting text\n");
  GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  gtk_text_buffer_set_text(buffer, long_text, -1);

  GtkRequisition req;
  gtk_widget_get_preferred_size(view, &req, NULL);
  printf("in button_clicked(): preferred height = %u\n", req.height);
  return false;
}

static bool on_size_allocate(GtkWidget* obj, GdkRectangle *allocation, GtkWidget* view)
{
  GtkRequisition req;
  gtk_widget_get_preferred_size(view, &req, NULL);
  printf("in on_size_allocate(): preferred height = %u\n", req.height);
  return false;
}

static void activate(GtkApplication* app, gpointer user_data)
{
  GtkWidget *window;
  window = gtk_application_window_new(app);
  gtk_window_set_title(GTK_WINDOW (window), "Wrapped text");
  gtk_window_set_default_size(GTK_WINDOW (window), 200, 200);
  gtk_widget_show_all(window);

  GtkTextBuffer* buffer = gtk_text_buffer_new(NULL);

  GtkWidget* view = GTK_WIDGET(gtk_text_view_new_with_buffer(buffer));
  g_object_unref(buffer);
  gtk_widget_set_size_request(view, 180, -1);
  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD_CHAR);
  g_signal_connect(view, "size-allocate", G_CALLBACK(on_size_allocate), view);

  GtkWidget *button = gtk_button_new_with_label("Set Text");
  g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), view);

  GtkWidget* grid = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(window), grid);
  gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1);
  gtk_grid_attach(GTK_GRID(grid), view, 0, 1, 1, 1);

  gtk_widget_show_all(window);
}

int main (int argc, char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
  status = g_application_run(G_APPLICATION(app), argc, argv);
  g_object_unref(app);

  return status;
}

This displays:

in on_size_allocate(): preferred height = 17
----------------------------
in button_clicked(): setting text
in button_clicked(): preferred height = 17
in on_size_allocate(): preferred height = 34
0

There are 0 best solutions below