Transient Warning

Hi,

Consider window is the main window of my project. label_1 is widget of a submenu. When I run this snippet I get:

[...]
// in main:
g_signal_connect(G_OBJECT(recents_ptr[i]),"activate"
                                ,G_CALLBACK(show_message_lm),(gpointer)str_ptr);
[...]
void show_message(const gchar * const message)
{

    GtkWidget*  dialog;

    //gtk_window_set_transient_for (dialog,window); // causes core dump
    dialog = gtk_message_dialog_new (GTK_WINDOW(window),
                                     GTK_DIALOG_DESTROY_WITH_PARENT,
                                     GTK_MESSAGE_INFO,
                                     GTK_BUTTONS_CLOSE,
                                     "Message: %s",
                                     message);


    /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
    g_signal_connect_swapped (dialog, "response",
                              G_CALLBACK (gtk_widget_destroy),
                              dialog);
    gtk_widget_show_all (dialog);

    return;
}
void show_message_lm(GtkWidget*label_1,gpointer message) 
{
    show_message(message);
    return;
}

I get:

Gtk-Message: 16:33:11.966: GtkDialog mapped without a transient parent. This is discouraged.

You don’t need to call gtk_window_set_transient_for() because gtk_message_dialog_new() already calls that when the parent parameter is non-NULL. Maybe you are passing a NULL value for parent?

you must pass to the function a pointer to the parent window of the message dialog
void show_message (const gchar * const message, gpointer user_data)

  • user_data pointer to the parent window

Since it seems to me that multi argument is to be passed between functions; What happens to show_message_lm and it’s g_signal_connect caller ? I suppose window should be local to main function.

Tell me something, what message do you want to display where it comes from?

The toy messages are part of a bigger open-source project. Basically message is uri of recent files. Later in actual code , I want to open these recent files ; When a sub-menu item is activated.

Here is my current try:

// in main()
[...]
gint i;
    for( i=0; i<RECENTS_COUNT; i++)
    {
        gchar stri[20];
        gchar *str_ptr;
        
        str_ptr=g_strdup_printf ("si is %d\n",i);
        
        g_signal_connect_data(G_OBJECT(recents_ptr[i]), "activate",
                               G_CALLBACK(choice_clicked),str_ptr, (GClosureNotify)g_free, 0);
        
        gpointer mes_par[]={str_ptr,window}; 
        g_signal_connect(G_OBJECT(recents_ptr[i]),"activate"
                                ,G_CALLBACK(show_message_caller),mes_par);

    }
[...]

void show_message ( gpointer* mes_par)
{

    GtkWidget*  dialog;
    gchar *  message=G_OBJECT(mes_par[0]); 
    GtkWidget* parent=GTK_WINDOW(mes_par[1]);
    
    dialog = gtk_message_dialog_new (GTK_WINDOW(parent),
                                     GTK_DIALOG_DESTROY_WITH_PARENT,
                                     GTK_MESSAGE_INFO,
                                     GTK_BUTTONS_CLOSE,
                                     "Message: %s",
                                     message);

    /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
    g_signal_connect_swapped (dialog, "response",
                              G_CALLBACK (gtk_widget_destroy),
                              dialog);
    gtk_widget_show_all (dialog);
    
    return;
}
void show_message_caller(GtkWidget*label_1,gpointer* mes_par)
{
    show_message(mes_par);
    return;
}

I get seg fault from running last code , is there a problem to solve ?

gdb is a good tool for debugging segfaults. Especially if you install debug symbols for glib and gtk. For memory problems, you can also try running with AddressSanitizer or valgrind.

Similar issue: mes_par[] is an auto array, allocated on the stack, and when the signal handler is called that address is being used for something else. Like str_ptr, you need to allocate memory for it, say with g_new(gpointer, 2), pass the address of that memory to g_signal_connect_data() instead of g_signal_connect(), and pass g_free as the GClosureNotify.

I do not believe in such debuggers. I try to avoid them. My major problem for now is that I can not enable warnings (GCC or Clang) like -Wall. If I do so the whole GTK is compiled from source as time taken suggest me. I can build from a static library only when no warning flag is on.

I’m sorry, but then you get to debug your code by yourself.

That’s unfortunate, but it’s your literally coding in the dark if you don’t use the facilities that the programming language provides you—a debugger and compiler warnings. Nobody else can help you.

[…]

The original open-source project , does include -Wall . I am viewing warnings for temp project in the terminal after compilation too.

If no debugger, no FLAGs…
Then do a call like g_print( “debug” ); every 30-50 line and see where gets no printed.

Once that you do no see it anymore…you check those lines.

Any way a segfault means that your App accessed some memory which does not belong to you or your program.

My toy code is based on this submenu.c code from this zetcode tutorial.

If license and other factors allow , I can post my code here.

I am still working to get the warnings on , I get core dumped after clicking a recent item , but here is may code based on zetcode tutorial till now:

// submenu of recent files.
// http://zetcode.com/gui/gtk2/menusandtoolbars/
// GTK 2
#include <gtk/gtk.h>
#include <glib.h>
#include <stdbool.h>
#include <assert.h>

#define RECENTS_COUNT 5

GtkWidget *recents_ptr[RECENTS_COUNT+1];
gchar recent_title[40];

typedef struct data
{
    gchar* str;
    GtkWidget* window;
}data;

void choice_clicked(GtkWidget * ,gpointer );
void produce_recent_items(void) ;
void show_message(data*);
void show_message_caller(GtkWidget*choice,gpointer);

int main(int argc, char *argv[])
{

    GtkWidget *window;
    GtkWidget *vbox;

    GtkWidget *menubar;
    GtkWidget *fileMenu;
    GtkWidget *imprMenu;
    GtkWidget *sep;
    GtkWidget *fileMi;
    GtkWidget *imprMi;
    GtkWidget *feedMi;
    GtkWidget *bookMi;

    GtkWidget *quitMi;

    GtkWidget *rec_labels[RECENTS_COUNT+1];

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
    gtk_window_set_title(GTK_WINDOW(window), "Submenu");

    produce_recent_items();
    assert(recents_ptr[0]!=NULL);

    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);

    menubar = gtk_menu_bar_new();

    fileMenu = gtk_menu_new();
    fileMi = gtk_menu_item_new_with_label("File");

    imprMenu = gtk_menu_new();
    imprMi = gtk_menu_item_new_with_label("Import");
    feedMi = gtk_menu_item_new_with_label("Import news feed...");
    bookMi = gtk_menu_item_new_with_label("Import bookmarks...");

    for(int i=0; i<RECENTS_COUNT; i++)
    {
        gchar *uri_l=gtk_recent_info_get_uri(recents_ptr[i]);

        rec_labels[i]=gtk_menu_item_new_with_label(uri_l);
    }

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(imprMi), imprMenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), feedMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), bookMi);

    sep = gtk_separator_menu_item_new();
    quitMi = gtk_menu_item_new_with_label("Quit");

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);

    for(int i=0; i<RECENTS_COUNT; i++)
        gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), recents_ptr[i]);

    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), imprMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
    gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);

    g_signal_connect(G_OBJECT(window), "destroy",
                     G_CALLBACK(gtk_main_quit), NULL);

    g_signal_connect(G_OBJECT(quitMi), "activate",
                     G_CALLBACK(gtk_main_quit), NULL);

    g_signal_connect(G_OBJECT(feedMi),"activate"
                     ,G_CALLBACK(choice_clicked),"Test str.");
    gint i;
    data* dip=g_new(data,RECENTS_COUNT+1); 

    for( i=0; i<RECENTS_COUNT; i++)
    {
        gchar stri[20];
        gchar *str_ptr;

        str_ptr=g_strdup_printf ("si is %d\n",i);

        g_signal_connect_data(G_OBJECT(recents_ptr[i]), "activate",
                               G_CALLBACK(choice_clicked), str_ptr, (GClosureNotify)g_free, 0);

        (dip+i)->str=str_ptr;
        (dip+i)->window=window;
        g_signal_connect_data(G_OBJECT(recents_ptr[i]),"activate"
                                ,G_CALLBACK(show_message_caller),(dip+i),(GClosureNotify)g_free, 0);

    }

                     gtk_widget_show_all(window);

                     gtk_main();

                     return 0;
}

void choice_clicked(GtkWidget *widget, gpointer str)
{
    g_print("%s\n",str);
    return;
}

void produce_recent_items(void) 
{ // TODO "file://" may be removed
    GtkRecentInfo *ri;
    GList *rf_list;
    const gchar *rf_str;
    GtkWidget *rf_widget;

    GtkRecentManager *manager=gtk_recent_manager_get_default();
    assert(manager!=NULL);
    GtkWidget *chooser=gtk_recent_chooser_menu_new_for_manager(manager);
    assert(chooser!=NULL);

    gtk_recent_chooser_set_limit (chooser,RECENTS_COUNT);
    rf_list=gtk_recent_chooser_get_items (chooser);
    assert(rf_list!=NULL);

    int i;
    for(i=0; i<RECENTS_COUNT; )
    {
        recents_ptr[i]=NULL;
        if(rf_list==NULL)
            break;

        ri=rf_list->data;
        bool this_app ;
        gchar * name = gtk_recent_info_last_application(ri);
        if(1)//(strstr(name,"xboard")) // true
            this_app=true;
        else
            this_app=false;
        if(this_app)
        {
            rf_str=gtk_recent_info_get_uri(ri);
            rf_widget=gtk_menu_item_new_with_label(rf_str); // TODO warning here
            recents_ptr[i]=rf_widget;
            i++;
        }
        rf_list=rf_list->next;
    }
    printf("i is %d\n",i);
    return;
}

void show_message ( data* mes_par) //
{

    GtkWidget*  dialog;
    gchar *  message=G_OBJECT(mes_par->str);
    GtkWidget* parent=GTK_WINDOW(mes_par->window);

    dialog = gtk_message_dialog_new (GTK_WINDOW(parent),
                                     GTK_DIALOG_DESTROY_WITH_PARENT,
                                     GTK_MESSAGE_INFO,
                                     GTK_BUTTONS_CLOSE,
                                     "Message: %s",
                                     message);

    // Destroy the dialog when the user responds to it (e.g. clicks a button)
    g_signal_connect_swapped (dialog, "response",
                              G_CALLBACK (gtk_widget_destroy),
                              dialog);
    gtk_widget_show_all (dialog);
    return;
}
void show_message_caller(GtkWidget*choice,gpointer mes_par)
{
    data *udp=mes_par;
    show_message(udp);
    return;
}