Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Tracking mouse movement with GTk+

Tags:

c

gtk

Consider the following code:

#include<gtk/gtk.h>
#include<stdio.h>


static void destroy(GtkWidget*, gpointer);
static gboolean mouse_moved(GtkWidget *widget,GdkEvent *event,gpointer user_data);

int main(int argc, char* argv[]) {

    GtkWidget *main_window;

    // initializing
    gtk_init(&argc, &argv);

    main_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(main_window),"Test");
    gtk_widget_set_size_request (main_window, 500, 300);

    // connect the window with signals
    g_signal_connect (G_OBJECT (main_window), "destroy",G_CALLBACK (destroy), NULL);
    g_signal_connect (G_OBJECT (main_window), "motion-notify-event",G_CALLBACK (mouse_moved), NULL);

    gtk_widget_set_events(main_window, GDK_POINTER_MOTION_MASK);

    // show window
    gtk_widget_show_all (main_window);

    gtk_main();
    return 0;
}


static void destroy(GtkWidget *window,gpointer data) {
    gtk_main_quit ();
}


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);
    }
}

When I run this code from terminal, it opens an empty window, and prints out the mouse coordinates at each time.
Here's (part of) the output from the last execution:

Coordinates: (390,17)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,19)
Coordinates: (390,19)
Coordinates: (390,19)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,23)
Coordinates: (391,23)
Coordinates: (391,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,29)
Coordinates: (390,29)
Coordinates: (390,29)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,31)
Coordinates: (390,31)
Coordinates: (390,32)
Coordinates: (390,32)
Coordinates: (390,32)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,34)
Coordinates: (390,34)
Coordinates: (390,34)
Coordinates: (389,34)
Coordinates: (389,35)
Coordinates: (389,36)
Coordinates: (389,36)
Coordinates: (389,36)
Coordinates: (389,37)
Coordinates: (389,36)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,38)
Coordinates: (389,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (381,43)
Coordinates: (381,43)
Coordinates: (381,43)
Coordinates: (380,43)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (379,44)
Coordinates: (378,44)
Coordinates: (378,44)
Coordinates: (377,44)
Coordinates: (377,44)

and so on...

What confuses me is this: How can there be two consecutive events holding the same coordinates? For example, take these two lines:

Coordinates: (380,44)
Coordinates: (380,44)  

This basically saying that the mouse hasn't been moving (it went from (380,44) to (380,44)), so how could there possibly be a movement event to launch the handler for that second line of input?


Another less important and (maybe) unrelated issue:
Why is this line necessary?

gtk_widget_set_events(main_window, GDK_POINTER_MOTION_MASK);

In the book Foundation Of Gtk+ Development it says:

Next, you need to add an event mask to the event box so that it knows what type of events the widget will receive. Values for the GdkEventMask enumeration that specify event masks are shown in Table 3-3. A bitwise list of GdkEventMask values can be passed to gtk_widget_set_events() if you need to set more than one.

But isn't this call redundant, given that we already have g_signal_connect()? which is, according to the documentation:

Connects a GCallback function to a signal for a particular object.

The handler will be called before the default handler of the signal.

Why do I need to register for a signal twice?
Once with gtk_widget_set_events() and second with g_signal_connect()?

like image 809
so.very.tired Avatar asked Mar 16 '15 17:03

so.very.tired


1 Answers

I tried monitoring the mouse movement in the X server directly using xev and it seems to be the case that xorg reports multiple mouse events with the same coordinates but different timestamps. When using the pointing stick on the keyboard however it didn't do this, only with the trackpad or an external mouse.

My guess would be that the precision is actually higher, but the events are reported for a pixel on the screen. This might cause the driver to report more mouse events then needed.

like image 92
Maurice Avatar answered Sep 21 '22 14:09

Maurice