Edit: I have found a solution for the simple example below, but it fails for my real application, and generates a critical warning on the example below. Through trial and error, I discovered that inserting gtk_main_quit ()
at the end of the activate
function successfully blocks the initial command line "Return". However, of course, it also generates a critical warning: Gtk-CRITICAL **: gtk_main_quit: assertion 'main_loops != NULL' failed
. Another thing that works for the example but I don't want in my application is to put up a "hello" dialog in the activate
function which the user has to dismiss.
I am working on a Gtk3 app that listens for the key-release-event, and I would like one of those events to be the "Return" key. The app will normally be started from a .desktop file, but may be started from a terminal too. When started from a terminal, it recognizes the initial "Return" that the user pressed to execute the app as a key-press. How can I avoid that? Here is a simple example "test_return.c"
/* gcc `pkg-config --cflags gtk+-3.0` -o test_return test_return.c `pkg-config --libs gtk+-3.0`
*/
#include <gtk/gtk.h>
static gboolean key_event_cb (GtkWidget *widget,
GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_KEY_Return) {
GtkWidget *dialog =
gtk_message_dialog_new (GTK_WINDOW(widget),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"Return");
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return TRUE;
}
return FALSE; //allow further processing of the keypress if it's not Return
}
static void activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_widget_show_all (window);
g_signal_connect (window, "key-release-event",
G_CALLBACK (key_event_cb), NULL); //keyboard events
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), 0, NULL);
g_object_unref (app);
return status;
}
What I want to happen is that it will not pop up a dialog until "Return" is pressed. When run from a terminal, it immediately shows the dialog because it recognizes the "Return" pressed in the terminal to start the app. When run from a .desktop file, it works as expected.
At first, I tried simply defining a gboolean that was TRUE at start, and FALSE after the first Return. That worked from the terminal, but then requred 2 Return key-presses when started from a .desktop file. My app will only be used in Linux (and in fact requires X11). I tried fflush(stdin);
, but it doesn't work. I even tried a timer to ignore Returns received in the first hundreth of a second using https://developer.gnome.org/glib/stable/glib-Timers.html, but I get strange behavior.
From the comments, I remembered that I've already tried waiting to connect the signal until the widget is fully drawn. It didn't work. Apparently, the "Return" key press is waiting in a buffer, but I can't figure out how to clear that buffer.
Also from the comments, I remembered that I already tried getchar() but that just waited for a character to be entered, completely ignoring the Return that I was trying to get rid of.
I edited main() replacing argc, argv with 0, NULL in the g_application_run funtion to ignore command line arguments, but that didn't help.