How to send a signal from a button while the callback function of other button didn't return signal back to main() in GTK+

StackOverflow https://stackoverflow.com/questions/23075862

  •  03-07-2023
  •  | 
  •  

Question

Here is a program in which there are two buttons (Connect and Disconnect). While clicking on 'connect' button, it calls 'button1_clicked_do_job()' function having while with some condition. On the other hand 'disconnect' button is used to change the condition of while. The problem is the Disconnect button is not working. How do I activate disconnect while 'connect' callback function didn't get returned to main()?

Here is the code:

#include<gtk/gtk.h>

static int check=1;
void button2_clicked_disconnect(GtkWidget *widget, gpointer data2)
{
    check=0; //Change the condition of while
}

void button1_clicked_do_job(GtkWidget *widget, gpointer data1)
{
    do{
        g_print("Accept Connection\n");
        sleep(2);
    } while(check==1);

    g_print("Reject Connection\n");
}

int main( int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
    GtkWidget *button1;
    GtkWidget *button2;

    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), 250, 150);
    gtk_window_set_title(GTK_WINDOW(window), "Connect_N__Disconnect");

    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);

    button1 = gtk_button_new_with_label("Connect");
    gtk_widget_set_size_request(button1, 80, 30);
    gtk_fixed_put(GTK_FIXED(fixed), button1, 30, 50);

    button2 = gtk_button_new_with_label("Disconnect");
    gtk_widget_set_size_request(button2, 80, 30);
    gtk_fixed_put(GTK_FIXED(fixed), button2, 130, 50);

    g_signal_connect(G_OBJECT(button1), "clicked",
                      G_CALLBACK(button1_clicked_do_job),   NULL);

    g_signal_connect(G_OBJECT(button2), "clicked",
                     G_CALLBACK(button2_clicked_disconnect), NULL);

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

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}
Was it helpful?

Solution

Generally speaking you should not run blocking code (like a long running while-loop) in the main thread because it makes the app unresponsive -- all functions should preferably return in milliseconds. In your case you also expect the main loop to call your other event handler but never give the main loop a chance to do it: the while loop just keeps executing forever. In other words: the first handler needs to return before the main loop can call the second one.

How to fix that depends on what your actual problem is: Using asynchronous code or idle handlers should be the first option, and a worker thread is another (but please only add threads when you know that you actually need them). It's also possible to "pump" the event loop manually but that should really be the last option. See main loop reference for details.

Your example would look something like this:

gboolean check_connection (gpointer user_data)
{
    /* g_print what you want based on check value */

    if (check == 0)
        return FALSE;
    return TRUE;
}

void button1_clicked_do_job(GtkWidget *widget, gpointer data1)
{
     g_timeout_add_seconds (2, check_connection, NULL);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top