/* Build with: gcc `pkg-config --cflags --libs gtk+-2.0` typing.c */ /* * The point of this program is to illustrate * https://bugs.freedesktop.org/show_bug.cgi?id=1738. * * It's a GTK+ app that has a window with two text fields labeled * "slow" and "normal". The normal one is a normal text field (what * else?). The slow one sleeps for 0,5s after each key press. * * If you press and hold "u" (for example), the slow box will keep * printing "u"s for long after you release the button. Bad. */ #include #include #include #define DELAY_MS 500 /* * Terminate the main loop. */ static void on_destroy (GtkWidget * widget, gpointer data) { (void)widget; (void)data; gtk_main_quit (); } /* * Slow down the slow text box. */ void delay(GtkEditable *editable, gpointer user_data) { (void)editable; (void)user_data; GdkWindow *updateMe; GdkRegion *bounds; usleep(DELAY_MS * 1000); // Repaint the widget updateMe = gtk_widget_get_parent_window(GTK_WIDGET(editable)); bounds = gdk_drawable_get_visible_region(updateMe); gdk_window_invalidate_region(updateMe, bounds, TRUE); gdk_region_destroy(bounds); gdk_window_process_updates(updateMe, TRUE); } int main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *table; GtkWidget *slowEntry; gtk_init (&argc, &argv); /* create the main, top level, window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* give it the title */ gtk_window_set_title (GTK_WINDOW (window), "Typing test"); /* open it a bit wider so that both the label and title show up */ gtk_window_set_default_size (GTK_WINDOW (window), 200, 50); /* Connect the destroy event of the window with our on_destroy function * When the window is about to be destroyed we get a notificaiton and * stop the main GTK loop */ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (on_destroy), NULL); /* Create the table used for layout */ table = gtk_table_new(2, 2, FALSE); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(gtk_label_new("Slow:")), 0, 1, 0, 1); slowEntry = gtk_entry_new(); g_signal_connect(G_OBJECT(slowEntry), "changed", G_CALLBACK(delay), NULL); gtk_table_attach_defaults(GTK_TABLE(table), slowEntry, 1, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(gtk_label_new("Normal:")), 0, 1, 1, 2); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(gtk_entry_new()), 1, 2, 1, 2); gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET(table)); /* make sure that everything, window and label, are visible */ gtk_widget_show_all (window); /* start the main loop */ gtk_main (); return 0; }