GTK3 rearrange items on grid when window resize

Hi, i am stuck in implementing a simple app with GTK3.
I want to display 9 GtkDrawingArea on a grid and rearrange them when the window is resized.
I connect the main window’s “size-allocate” event to a callback function that removes all grid widgets and set them to the desired location. This function works as expected.
Now i want to get click event on the GtkDrawingArea. I do this (just for test on one GtkDrawingArea)

gtk_widget_add_events (app.img[0], GDK_BUTTON_PRESS_MASK);
g_signal_connect (app.img[0], "button-press-event", G_CALLBACK (button_press_event), NULL);

But seems that the GtkDrawingArea do not respond to a “button-press-event”.
I found that this is related to the code used in the “size-allocate” event callback function (if i do not connect the size-allocate signal, the GtkDrawingArea will respond to a “button-press-event”).
I don’t know how to make it work as expected.

Here is the full code

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

struct app_wdg {
    GtkWidget *grd;
    GtkWidget *win;
    GtkWidget *sll;
    GtkWidget *img[9];
};

void add_images(struct app_wdg *app)
{
    gint i=0, x=0, y=0;
    gint width=0;
    gint height=0;

    width = gtk_widget_get_allocated_width(app->sll);

    for(i = 0; i < 9; i = i + 1)
    {
        gtk_grid_attach(GTK_GRID(app->grd), app->img[i], x, y, 1, 1);
        x = x + 1;
        if ((x+1)*100 + 30 >= width)
        {
            x = 0;
            y = y + 1;
        }
    }
}

static gboolean button_press_event (GtkWidget* self, GdkEventButton *event)
{
    g_print("Clicked!\n");
    return TRUE;
}

static void size_allocate (GtkWidget* self, GtkAllocation* allocation, gpointer user_data)
{
    struct app_wdg *app = (struct app_wdg *)(user_data);

    GList *children = gtk_container_get_children(GTK_CONTAINER(app->grd));
    for (const GList *iter = children; iter != NULL; iter = g_list_next(iter))
    {
        g_object_ref(iter->data);
        gtk_container_remove(GTK_CONTAINER(app->grd), iter->data);
    }

    add_images(app);

}

static gboolean on_draw (GtkWidget *self, cairo_t *cr, gpointer data)
{
    GdkPixbuf *pix;
    GError *err = NULL;

    pix = gdk_pixbuf_new_from_file(data, NULL);
    pix = gdk_pixbuf_scale_simple(pix, 100, 100, GDK_INTERP_NEAREST);
    gdk_cairo_set_source_pixbuf(cr, pix, 0, 0);
    cairo_paint(cr);

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 3);
    cairo_rectangle(cr, 0, 0, 100, 100);
    cairo_stroke(cr);

    return TRUE;
}

int main (int argc, char *argv[])
{
    struct app_wdg app;

    /* Initialize GTK+ */
    gtk_init (&argc, &argv);

    /* Create widgets */

    app.win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    app.grd = gtk_grid_new ();
    app.sll = gtk_scrolled_window_new (NULL, NULL);

    app.img[0] = gtk_drawing_area_new ();
    app.img[1] = gtk_drawing_area_new ();
    app.img[2] = gtk_drawing_area_new ();
    app.img[3] = gtk_drawing_area_new ();
    app.img[4] = gtk_drawing_area_new ();
    app.img[5] = gtk_drawing_area_new ();
    app.img[6] = gtk_drawing_area_new ();
    app.img[7] = gtk_drawing_area_new ();
    app.img[8] = gtk_drawing_area_new ();
    gtk_widget_set_size_request (app.img[0], 100, 100);
    gtk_widget_set_size_request (app.img[1], 100, 100);
    gtk_widget_set_size_request (app.img[2], 100, 100);
    gtk_widget_set_size_request (app.img[3], 100, 100);
    gtk_widget_set_size_request (app.img[4], 100, 100);
    gtk_widget_set_size_request (app.img[5], 100, 100);
    gtk_widget_set_size_request (app.img[6], 100, 100);
    gtk_widget_set_size_request (app.img[7], 100, 100);
    gtk_widget_set_size_request (app.img[8], 100, 100);

    /* Set widgets */

    /* win */
    gtk_container_set_border_width (GTK_CONTAINER (app.win), 8);
    gtk_window_set_title (GTK_WINDOW (app.win), "img_tab");
    gtk_window_set_position (GTK_WINDOW (app.win), GTK_WIN_POS_CENTER);
    gtk_widget_set_size_request (app.win, 300, 300);
    /* grid */
    gtk_grid_set_column_spacing(GTK_GRID(app.grd),6);
    gtk_grid_set_row_spacing(GTK_GRID(app.grd),6);

    /* Add widgets to containers */

    gtk_container_add(GTK_CONTAINER(app.win), app.sll);
    gtk_container_add(GTK_CONTAINER(app.sll), app.grd);

    add_images(&app);

    /* Add callbacks */
    g_signal_connect (app.win, "size-allocate", G_CALLBACK (size_allocate), &app);
    g_signal_connect (app.win, "destroy", gtk_main_quit, NULL);

    g_signal_connect (app.img[0], "draw", G_CALLBACK (on_draw), "./bin/Debug/0.png");
    g_signal_connect (app.img[1], "draw", G_CALLBACK (on_draw), "./bin/Debug/1.png");
    g_signal_connect (app.img[2], "draw", G_CALLBACK (on_draw), "./bin/Debug/2.png");
    g_signal_connect (app.img[3], "draw", G_CALLBACK (on_draw), "./bin/Debug/3.png");
    g_signal_connect (app.img[4], "draw", G_CALLBACK (on_draw), "./bin/Debug/4.png");
    g_signal_connect (app.img[5], "draw", G_CALLBACK (on_draw), "./bin/Debug/5.png");
    g_signal_connect (app.img[6], "draw", G_CALLBACK (on_draw), "./bin/Debug/6.png");
    g_signal_connect (app.img[7], "draw", G_CALLBACK (on_draw), "./bin/Debug/7.png");
    g_signal_connect (app.img[8], "draw", G_CALLBACK (on_draw), "./bin/Debug/8.png");

    gtk_widget_add_events (app.img[0], GDK_BUTTON_PRESS_MASK);
    g_signal_connect (app.img[0], "button-press-event", G_CALLBACK (button_press_event), NULL);

    /* Enter the main loop */
    gtk_widget_show_all (app.win);
    gtk_main ();
    return 0;
}

Widgets in GTK3 do not automatically handle events: you will need to put the drawing area inside a GtkEventBox first.

No, that has nothing to do with size allocation. You’re just getting a result because you’re breaking the widget.

You’re also breaking the widget in a much worse way:

You must not add or remove widgets, or do anything that will cause a new layout in the middle of a layout phase—which is what size_allocate() is. You are breaking the toolkit in a very bad way, and you’ll never get it working the way you want.

GtkGrid is a scaffolding widget, just like GtkBox: it’s not meant to be used to dynamically reallocate all the children on resize. Instead of abusing GtkGrid, use GtkFlowBox, which does exactly what you want: reflowing children widgets in a row/column.

Thanks so much for your help.
I am a newbie and didn’t know about the GtkFlowBox widget! It’s exactly what I need.