ccallbackgtk3gladegtk2

g_signal_connect_swapped fails to connect


I have tried past one month learning to use gtk for an application and migrating its code from gtk2 to gtk3. But, one button in a gtk dialog doesn't seem to work well, inspite of whatever i chose the dialog closes without calling the callback function.

int validation_pmu_server (GtkButton *button, gpointer udata)
{

/* local variables */
int tmp_p;
char *msg;
const char *text1, *text2;

/* Get the text entries filled by user */
text1 = gtk_entry_get_text(GTK_ENTRY(p_port));
text2 = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(p_protocol));

if(!isNumber((char *)text1) && (atoi(text1) < 1500 || (atoi(text1) > 65535)))   /* Check for valid port number */       
{ 
    msg = "\tPlease enter valid value for PMU Server Port\t\n";
    validation_result (msg);        /* Show the unsuccess message to user */
    return 0;
}
else
{
    strncpy(PMUprotocol, text2, 3);
    PMUport = atoi(text1);

    if(!strcmp(text2, "UDP"))
        tmp_p = 1;          
    else
        tmp_p = 2;          

    p1 = *ShmPTR;
    p1.cfg_bit_change_info = 0;
    ShmPTR->cfg_bit_change_info = 0;
    ShmPTR->serverProtocol = tmp_p;
    ShmPTR->serverPort = atoi(text1);

    p1.pid = ShmPTR->pid;

    kill(p1.pid, SIGUSR2);
    printf("PORT & Protocol information has sent to PMU Server through signal.\n");

    memset(pmuFilePath, '\0', 200);

    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->start_server), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->open_cfg), FALSE);

    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->create_cfg_button), TRUE);                    
    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->menu_setup_cfg), TRUE);                   

    /* Close/destroy the pmu_server_window */
    gtk_widget_destroy(pmu_server_window);

    return 1;
}
};

void pmu_server ()
{
/* local variables */
GtkWidget *table, *label, *cancel_button;
GtkWidget *valdbutton, *help_button;

/* Create a new dialog window for PMU Server Setup */
pmu_server_window = gtk_dialog_new ();
g_signal_connect (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
gtk_window_set_title (GTK_WINDOW (pmu_server_window), "PMU Server Setup");
gtk_container_set_border_width (GTK_CONTAINER (pmu_server_window), 10);

/* Create a table of 4 by 2 squares. */
table = gtk_grid_new (); // table = gtk_table_new (6, 2, FALSE);

/* Set the spacing to 50 on x and 5 on y */
gtk_grid_set_row_spacing (GTK_GRID(table), 16); // gtk_table_set_row_spacings (GTK_TABLE  (table), 8);
gtk_grid_set_column_spacing (GTK_GRID(table), 16); // gtk_table_set_col_spacings (GTK_TABLE  (table), 2);

/* Pack the table into the window */
//gtk_box_pack_start (GTK_BOX (GTK_DIALOG(pmu_server_window)->vbox), table, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG(pmu_server_window))), table, TRUE, TRUE, 0);
gtk_widget_show (table);

/* Add few buttons to the bottom of the dialog */
valdbutton = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Run", GTK_RESPONSE_OK); // gtk_button_new_with_label ("Run");
help_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Help", GTK_RESPONSE_APPLY); // gtk_button_new_with_label ("Help");
cancel_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Cancel", GTK_RESPONSE_CLOSE); //gtk_button_new_with_label ("Cancel");

/* This simply creates a grid of toggle buttons on the table */
label = gtk_label_new (" ");
markup = g_markup_printf_escaped ("<span foreground=\"#990033\" font='12'><b>Enter PMU Server Details</b></span>");
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_grid_attach (GTK_GRID (table), label, 0,0,2,1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 0, 1);
gtk_widget_show (label);
g_free (markup);

label = gtk_label_new ("Server Port");
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
gtk_widget_show (label);

label = gtk_label_new ("Protocol");
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
gtk_widget_show (label);

/* Create text boxes for user to enter appropriate values */
p_port = gtk_entry_new();
gtk_entry_set_max_length ((GtkEntry *)p_port, 5);
gtk_grid_attach (GTK_GRID (table), p_port, 1, 2, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), p_port, 1, 2, 2, 3);
gtk_widget_show (p_port);

label = gtk_label_new (" ");
markup = g_markup_printf_escaped ("<span foreground=\"#333333\" font='8'><b>Note : Use the unreserved ports for PMU Server.</b></span>");
gtk_label_set_markup (GTK_LABEL (label), markup);
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 5, 2, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 5, 6);
gtk_widget_show (label);
g_free (markup);

/* Create combo boxe for user with some fixed values */
p_protocol = gtk_combo_box_text_new();
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p_protocol), "UDP");
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p_protocol), "TCP");
gtk_combo_box_set_active(GTK_COMBO_BOX(p_protocol), 0);
gtk_grid_attach (GTK_GRID (table), p_protocol, 1, 3, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), p_protocol, 1, 2, 3, 4);
gtk_widget_show (p_protocol);

/* Signal handling for buttons on PMU Server Setup Window */
g_signal_connect_swapped (valdbutton, "clicked", G_CALLBACK (validation_pmu_server), valdbutton);
g_signal_connect_swapped (help_button, "clicked", G_CALLBACK (Pmu_Help), NULL);
g_signal_connect_swapped (cancel_button, "clicked", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);

/* This makes it so the button is the default. */
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), valdbutton, TRUE, TRUE, 0);
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), help_button, TRUE, TRUE, 0);
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), cancel_button, TRUE, TRUE, 0);        

/* This grabs this button to be the default button. Simply hitting the "Enter" key will cause this button to activate. */
gtk_widget_grab_default (valdbutton);
gtk_widget_show (valdbutton);
gtk_widget_grab_default (help_button);
gtk_widget_show (help_button);
gtk_widget_grab_default (cancel_button);
gtk_widget_show (cancel_button);

/* Finally show the pmu_server_window */
gtk_widget_show (pmu_server_window);
};

The function pmu_server creates a dialog as shown in this image

as per my code when run button is clicked validation_pmu_server is supposed to be called but rather the dialog box simply closes as if the gtk_widget_destroy was called. some of the commented code is the old gtk2 code which i migrated to gtk3.

PS : The above code change from gtk2 to gtk3 is done using this reference Though I was able to make my code work somewhow, I please request anyone with knowledge to help me understand why this is happening.


Solution

  • The problem you are facing is because of response signal. Whenever any action widget(in your case dialog buttons) is clicked, the response signal is emitted before any other signal(clicked signal). So the function callback associated with signal response will be executed first and then the callback associated with the clicked signal. So, the gtk_widget_destroy is getting called up first and your dialog is closing.

    You can either change the callback associated with response or use any other signal.

    I have used the below standalone code to reproduce the issue.

    #include<stdio.h>
    #include <gtk/gtk.h>
    
    
    void Pmu_Help(){
        printf("Pmu_Help");
        fflush(stdout);
    }
    void validation_pmu_server(){
        printf("validation_pmu_server");
        fflush(stdout);
    }
    void response(){
        printf("response");
        fflush(stdout);
    }
    
    
    int main(int argc, char *argv[]) {
    
        GtkWidget *window;
        GtkWidget * pmu_server_window;
    
        gtk_init(&argc, &argv);
    
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_widget_show(window);
      
        g_signal_connect(window, "destroy",
          G_CALLBACK(gtk_main_quit), NULL);
    
        pmu_server_window = gtk_dialog_new ();
        g_signal_connect (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
        gtk_window_set_title (GTK_WINDOW (pmu_server_window), "PMU Server Setup");
        gtk_container_set_border_width (GTK_CONTAINER (pmu_server_window), 10);
    
        GtkWidget *table, *label, *cancel_button;
        GtkWidget *valdbutton, *help_button;
    
        valdbutton = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Run", GTK_RESPONSE_OK); // gtk_button_new_with_label ("Run");
        help_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Help", GTK_RESPONSE_APPLY); // gtk_button_new_with_label ("Help");
        cancel_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Cancel", GTK_RESPONSE_CLOSE); //gtk_button_new_with_label ("Cancel");
    
        g_signal_connect_swapped (valdbutton, "clicked", G_CALLBACK (validation_pmu_server), valdbutton);
        g_signal_connect_swapped (help_button, "clicked", G_CALLBACK (Pmu_Help), NULL);
        g_signal_connect_swapped (cancel_button, "clicked", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
        g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (response), pmu_server_window);
        //g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
        gtk_widget_show(pmu_server_window);
    
        gtk_main();
    
      return 0;
    }