How do I get Keyboard and Mouse Input in GTK?

2019-04-14 07:16发布

I want to recieve keyboard and mouse input in GTK+. For keyboard input, I tried using the accelgroup but it wasn't somehow as smooth as say SDL or SFML. When I pressed a key. It responded, paused for some time, responded again, pause for sometime and so on. By Mouse input I mean getting the position of the Mouse at a given time and whether a mouse button is clicked. By keyboard input I want to track keypresses and releases. I am using GTK+ and cairo for an Educational Graphics Program. Kind of like the Turtle Graphics. Any Help? Or Any third party library (C or C++) that works with GTK+ and tracks keyboard and mouse input?

标签: c++ c input gtk
3条回答
不美不萌又怎样
2楼-- · 2019-04-14 07:49

According to the docs]1 you can get mouse motion events setting them a mask of GDK_POINTER_MOTION_MASK - that means you will get motion events even though no buttons are pressed. Also, Gtk+ tutorials show some notion of utilizing mouse motion events.

When I pressed a key. It responded, paused for some time, responded again, pause for sometime and so on.

What do you mean by this? I think you are describing key repeat behaviour (the same as in a text editor when you press 'a' and hold it, you get 'aaaaaaaaaaaaa'. To disable it in your app:

XKeyboardControl control; 
control.auto_repeat_mode = 0; 

gdk_error_trap_push (); 
XChangeKeyboardControl (GDK_DISPLAY (), KBAutoRepeatMode, &control); 
gdk_error_trap_pop (); 
查看更多
家丑人穷心不美
3楼-- · 2019-04-14 08:07

Here is an example code demonstration of how to use callbacks to register mouse movement and key presses:

// compile with: gcc example.c `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0`
#include <stdio.h>
#include <gtk/gtk.h>

static gboolean is_w_pressed = FALSE;
static gboolean is_a_pressed = FALSE;
static gboolean is_s_pressed = FALSE;
static gboolean is_d_pressed = FALSE;
static gboolean is_q_pressed = FALSE;
static gboolean is_e_pressed = FALSE;

static gboolean mouse_moved(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    if (event->type == GDK_MOTION_NOTIFY)
    {
        GdkEventMotion *e = (GdkEventMotion*)event;
        printf("Coordinates: (%u, %u)\n", (guint)e->x, (guint)e->y);
    }
}

static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
    if (event->keyval == GDK_KEY_w)
    {
        is_w_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_a)
    {
        is_a_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_s)
    {
        is_s_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_d)
    {
        is_d_pressed = TRUE;
        return TRUE;
    }
    return FALSE;
}

static gboolean key_released(GtkWidget *widget, GdkEventKey *event)
{
    if (event->keyval == GDK_KEY_w) {
        is_w_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_a) {
        is_a_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_s) {
        is_s_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_d) {
        is_d_pressed = FALSE;
    }
    return GDK_EVENT_PROPAGATE;
}

gboolean update (GtkWidget *widget, GdkFrameClock *clock, gpointer data)
{
    if (is_w_pressed) {
        printf("W key pressed!\n");
    }
    if (is_a_pressed) {
        printf("A key pressed!\n");
    }
    if (is_s_pressed) {
        printf("S key pressed!\n");
    }
    if (is_d_pressed) {
        printf("D key pressed!\n");
    }
    printf("updating...\n");
}

int main(int argc, char *argv[]) {
    GtkWidget *window;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_events(window, GDK_KEY_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK);
    gtk_widget_set_size_request(window, 320, 240);
    g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(mouse_moved), NULL);
    g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(key_pressed), NULL);
    g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(key_released), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_add_tick_callback(window, update, NULL, NULL);
    gtk_widget_show_all(window);
    gtk_main(); 
    return 0;
}
查看更多
再贱就再见
4楼-- · 2019-04-14 08:09

What you want to do is moderately complex. Take a look at

http://developer.gnome.org/gtk-tutorial/2.90/

and especially at

http://developer.gnome.org/gtk-tutorial/2.90/x344.html

and

http://developer.gnome.org/gtk-tutorial/2.90/c2422.html

The second link has source code for a keyboard callback that seems to do what you want. The third link is the beginning of a tutorial for a simple drawing program that uses the mouse.

EDIT: For the sake of completeness, I'll mention that the gtkglext library supports the use of OpenGL within GTK+. See

http://projects.gnome.org/gtkglext/

查看更多
登录 后发表回答