简体   繁体   中英

Ignore keyboard cursor in GTK3 C

Using GTK3 in C, I have an interface with buttons. I want a user with a mouse to be able to press a button OR use press a single button on the keyboard to do the same thing.

MWE (modified from GTK3 Hello World example):

/*
 * Ignore keyboard cursor in GTK3 C
 */

#include <gtk/gtk.h>

void thing() {
    printf("did a thing\n");
}

void otherthing() {
    printf("did something different\n");
}

static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
    gchar* val = gdk_keyval_name (event->keyval);

    if (strcmp(val, "Left") == 0) {
        thing();
    }
    return 0;
}

static void activate (GtkApplication *app, gpointer user_data) {
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *button2;
    GtkWidget *button_box;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_container_add (GTK_CONTAINER (window), button_box);

    button = gtk_button_new_with_label ("Do the thing");
    button2 = gtk_button_new_with_label ("xxx");
    g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
    g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
    g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
    gtk_container_add (GTK_CONTAINER (button_box), button2);
    gtk_container_add (GTK_CONTAINER (button_box), button);

    gtk_widget_show_all (window);
}

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), argc, argv);
    g_object_unref (app);

    return status;
}

In this program, the user can press the left arrow key to execute thing . The user can also click on the gui button to execute thing . However, hitting certain keyboard keys such as space or enter will "click" on the gui button to execute thing .

How do I prevent the keyboard from "clicking" on a button which the keyboard cursor is on in this case?

Fake Button Hack

I have hacked a workaround into my code for now using a useless button. I will not be marking this answer as solved since it is very sloppy, but it does the job until something better becomes available.

Description

This hack adds another button with no functions assigned. Using gtk_widget_grab_focus , we force this useless "fakebutton" to hold keyboard focus. We reissue this command every time a button is pressed.

Problems

Grabbing focus back to the fakebutton is slow. The user can issue a quick succession of commands (in the case of the MWE by pressing Left and Space to erroneously issue the otherthing function).

MWE

/*
 * Ignore keyboard cursor in GTK3 C
 */

#include <gtk/gtk.h>

GtkWidget *fakebutton;

void thing() {
    printf("did a thing\n");
}

void otherthing() {
    printf("did something different\n");
}

static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
    gchar* val = gdk_keyval_name (event->keyval);

    if (strcmp(val, "Left") == 0) {
        thing();
        gtk_widget_grab_focus(fakebutton);
    } else {
        gtk_widget_grab_focus(fakebutton);
    }
    return 0;
}

static void activate (GtkApplication *app, gpointer user_data) {
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *button2;
    GtkWidget *button_box;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_container_add (GTK_CONTAINER (window), button_box);

    button = gtk_button_new_with_label ("Do the thing");
    button2 = gtk_button_new_with_label ("xxx");
    fakebutton = gtk_button_new();
    g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
    g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
    g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
    gtk_container_add (GTK_CONTAINER (button_box), button2);
    gtk_container_add (GTK_CONTAINER (button_box), fakebutton);
    gtk_container_add (GTK_CONTAINER (button_box), button);


    gtk_widget_show_all (window);
}

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), argc, argv);
    g_object_unref (app);

    return status;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM