You have to force GTK to run the event loop and clear all pending events, one of which is a redraw triggered by gtk_widget_set_sensitive
that didn't have time, yet, to be handled. Here is a complete working example using GTK3:
#include <unistd.h> // sleep()
#include <gtk/gtk.h>
void simulate_long_curl_request(GtkWidget *widget)
{
sleep(5);
gtk_widget_set_sensitive(widget, true);
}
static void on_login_pressed(GtkWidget *loginButton, GdkEvent *event, gpointer data)
{
gtk_widget_set_sensitive(loginButton, false);
// Force GTK to treat pending events in the event loop
// before moving on. This includes your `set_sensitive`
// call the line before...
while(gtk_events_pending())
{
gtk_main_iteration();
}
simulate_long_curl_request(loginButton);
}
void on_activate(GtkApplication *application, gpointer user_data)
{
// Setup application window:
GtkWidget *loginWindow;
loginWindow = gtk_application_window_new(application);
gtk_window_set_title(GTK_WINDOW(loginWindow), "Login window");
gtk_window_set_default_size(GTK_WINDOW(loginWindow), 200, 200);
// Setup login button:
GtkWidget *loginButton;
loginButton = gtk_button_new_with_label("Login");
g_signal_connect(loginButton, "clicked", G_CALLBACK(on_login_pressed), NULL);
// Add button to window:
gtk_container_add(GTK_CONTAINER(loginWindow), loginButton);
// Run application:
gtk_widget_show_all(loginWindow);
}
int main(int argc, char **argv)
{
// Setup application:
GtkApplication *application;
application = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect(application, "activate", G_CALLBACK(on_activate), NULL);
const int status = g_application_run(G_APPLICATION(application), argc, argv);
g_object_unref(application);
return status;
}
You can read about the main loop here. You mentioned how gtk_widget_queue_draw
did not work. The description of the function says (my emphasis):
Invalidates the area of widget defined by region by calling gdk_window_invalidate_region()
on the widget’s window and all its child windows. Once the main loop becomes idle (after the current batch of events has been processed, roughly), the window will receive expose events for the union of all regions that have been invalidated.
So the function does not really redraw, it only sends a request to the main loop to redraw once it can. The call to gtk_widget_set_sensitive
most probably makes a call, internally, to gtk_widget_queue_draw
.
Be careful with this solution, though, as the following lines:
while(gtk_events_pending())
{
gtk_main_iteration();
}
will force-handle all events, including keyboard events and so on...