Search code examples
ctooltipgtk3

How to display a GTK tooltip for a short amount of time using C?


I have an application in which, on a button click, I want to display a tooltip, and then hide it after some time delay. The time delay is implemented using https://stackoverflow.com/a/3930477/6286575.

Here's what I have tried.

#include <gtk/gtk.h>
#include <stdio.h>
#include <time.h>

// https://stackoverflow.com/a/3930477/6286575
void wait(int unsigned delay)
{
    int unsigned end_time = time(0) + delay;
    while(time(0) < end_time);
}

void show_tooltip(GtkWidget *widget, gpointer data)
{
    GtkWidget **window = data;
    printf("Showing tooltip.\n");
    gtk_widget_set_tooltip_text(*window, "Clicked!");
    wait(5);
    // printf("Hiding tooltip.\n");
    // gtk_widget_set_has_tooltip(*window, FALSE);
}

int main(void)
{
    gtk_init(0, NULL);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    GtkWidget *grid = gtk_grid_new();
    gtk_container_add(GTK_CONTAINER(window), grid);

    GtkWidget *button = gtk_button_new_with_label("Click Me");
    gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1);
    g_signal_connect(GTK_BUTTON(button), "clicked", G_CALLBACK(show_tooltip), &window);

    gtk_widget_show_all(window);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_main();
}

Expectation

The tooltip should displayed immediately after Showing tooltip. appears on the terminal.

Observation

The tooltip is displayed after approximately 5 seconds after Showing tooltip. appears on the terminal.

How can I ensure that the tooltip is displayed at the same time as Showing tooltip. is printed? After the wait(5); delay, I would like to hide the tooltip, so that, effectively, the tooltip is visible only for a short amount of time.

To run the code, GTK3 is required.

sudo apt install libgtk-3-dev
gcc $(pkg-config --libs --cflags gtk+-3.0) main.c
./a.out

Solution

  • GUI is drawn in mainloop. When you call sleep() you freeze it for some time and it does nothing: no redrawing, no feedback for user input etc. You must show the tooltip and schedule a function which will hide the tooltip later.

    gboolean hide_tooltip (gpointer data)
    {
        GtkWidget *widget = data;
        gtk_widget_set_has_tooltip (widget, FALSE);
    
        return G_SOURCE_REMOVE; // same as FALSE. otherwise this function will be called again;
    }
    
    void show_tooltip (GtkWidget *widget, gpointer data)
    {
        GtkWidget **window = data;
        printf("Showing tooltip.\n");
        gtk_widget_set_tooltip_text(*window, "Clicked!");
    
        // Schedule 
        g_timeout_add (5 * G_TIME_SPAN_MILLISECOND, hide_tooltip, *window);
    }