Signal flooding (draw signal)

OK, did a first test, see code below.

This is for Gnome3 shell, x11-libs/gtk±3.24.8:3::gentoo USE="X cups introspection wayland

At first it looks fine, two draw signal emissions when I launch the program from within a shell. There may be reason why it are two. No emission when I move the mouse over its window or move the window around on the desktop. But when that window is the active one and I click into another window on the desktop, so that window will become inactive: 13 emissions, meaning 13 redraws for a custom drawing area. The other direction seems to be much better, when I click again in that test window to make it again active, there is only one draw signal emitted! (So there seems to be no hidden animation involved.) But 13 draw signals for making it inactive? Smells like really bad code.

But that is still OK, making a window inactive does not occur that often. More important is, what happens when widgets like drawing-area are embedded in containers beside scrollbars. Can be a nightmare when code is really bad. Have bad memories, but maybe that was still for old GTK2. Will continue testing…

// https://developer.gnome.org/gnome-devel-demos/stable/hello-world.html.en
// gcc filename.c `pkg-config --cflags --libs gtk+-3.0` -o filename

#include <gtk/gtk.h>
#include <stdio.h>

static gboolean
draw_cb (GtkWidget *widget,
         cairo_t   *cr,
         gpointer   data)
{
  //cairo_set_source_surface (cr, surface, 0, 0);
  //cairo_paint (cr);
  printf("draw_cb called\n");
  return FALSE;
}

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;
  GtkWidget *label;

  window = gtk_application_window_new (app);
  label = gtk_label_new ("Hello GNOME!");
  g_signal_connect (label, "draw",
                    G_CALLBACK (draw_cb), NULL);
  gtk_container_add (GTK_CONTAINER (window), label);
  gtk_window_set_title (GTK_WINDOW (window), "Welcome to GNOME");
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 100);
  gtk_widget_show_all (window);
}

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

  app = gtk_application_new (NULL, 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;
}

Hi Stefan,

I tested your example out using Ubuntu16.04 with unity and GTK version 3.18.9 and jhbuild of 3.22.26. I get the 2 draw emissions on start up but only one when I click into another window. Something isn’t working correctly there.

I noticed that you are connecting the “draw” callback to a label. Not sure how compatible that is. With css a label has a window to draw on but at one time a label didn’t have a window to draw on and used the background window. There is gtk_widget_set_app_paintable() to tell GTK that you want to draw on a widget yourself and ignore css. This works for me with a GtkWindow but gtk_widget_set_app_paintable() might be ignored for a label. I don’t know.

Eric

Thanks for testing. I am happy that you do not get the 13 draw events, so there is some hope that this behaviour is indeed an error that will be fixed eventually. Maybe it is an wayland issue.

Indeed I remembered that label widgets are special in some way, if I remember correctly they have no event box. Label was used, as I copied the code from official GTK3 example – I hate to type plain C. But I already replaced it with a drawing-area, which is what is actually used in my code, and I added some other signals, just to see when they are fired. Surprise was, that configure-event seems to be fired on wayland only when window is resized, that seems to be identical to size-allocation signal then. While from current GTK3 docs we have

The ::configure-event signal will be emitted when the size, position or stacking of the widget 's window has changed.

My latest code is below. This is what I get when I launch the prog from shell:

size_allocate_cb called
configure_event_cb called
realize_cb called
draw_cb called
draw_cb called

And this when I click in the shell window or gedit window once:

draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called
draw_cb called

For each resize of the test window I get following output, which is fine:

configure_event_cb called
size_allocate_cb called
draw_cb called

// https://developer.gnome.org/gnome-devel-demos/stable/hello-world.html.en
// gcc filename.c pkg-config --cflags --libs gtk+-3.0 -o filename

#include <gtk/gtk.h>
#include <stdio.h>

static gboolean
draw_cb (GtkWidget *widget,
         cairo_t   *cr,
         gpointer   data)
{
  printf("draw_cb called\n");
  return FALSE;
}

static gboolean
configure_event_cb (GtkWidget *widget,
               GdkEvent  *event,
               gpointer   user_data)
{
  printf("configure_event_cb called\n");
}

static void
size_allocate_cb (GtkWidget    *widget,
               GdkRectangle *allocation,
               gpointer      user_data)
{
  printf("size_allocate_cb called\n");
}


static void
realize_cb (GtkWidget *widget,
         gpointer   data)
{
  printf("realize_cb called\n");
}

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;
  GtkWidget *label;

  window = gtk_application_window_new (app);
  label = gtk_drawing_area_new();//gtk_label_new ("Hello GNOME!");
  g_signal_connect (label, "draw",
                    G_CALLBACK (draw_cb), NULL);
  g_signal_connect (label, "realize",
                    G_CALLBACK (realize_cb), NULL);
  g_signal_connect (label, "size-allocate",
                    G_CALLBACK (size_allocate_cb), NULL);
  g_signal_connect (label, "configure-event",
                    G_CALLBACK (configure_event_cb), NULL);

  gtk_widget_set_events (label, GDK_STRUCTURE_MASK);



  gtk_container_add (GTK_CONTAINER (window), label);
  gtk_window_set_title (GTK_WINDOW (window), "Welcome to GNOME");
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 100);
  gtk_widget_show_all (window);
}

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

  app = gtk_application_new (NULL, 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 topic was automatically closed 14 days after the last reply. New replies are no longer allowed.