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?
问题:
回答1:
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/
回答2:
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:
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;
}