Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to insert synthetic mouse events into X11 input queue

I've got an embedded device running Linux/X11 that is connected to a device that provides touch events over a USB connection. This device is not recognized as any form of standard pointer/mouse input. What I'm trying to do is find a way to "inject" mouse events into X11 when the external device reports an event.

Doing so would remove the need for my application ( written in C using Gtk+ ) to fake mouse presses with Gtk+ calls.

If this can be done my Gtk+ application would not need to know or care about the device generating the touch events. It would just appear to the application as standard mouse events.

Anybody know how to go about inserting synthetic mouse events into X11?

Right now I'm doing the following which works, but isn't optimal.

GtkWidget *btnSpin;     /* sample button */

gboolean buttonPress_cb( void *btn );
gboolean buttonDePress_cb( void *btn );


/*  make this call after the device library calls the TouchEvent_cb() callback
    and the application has determined which, if any, button was touched

    In this example we are assuming btnSpin was touched.

    This function will, in 5ms, begin the process of causing the button to do it's 
    normal animation ( button in, button out effects ) and then send the actual
    button_clicked event to the button.
*/
g_timeout_add(5, (GSourceFunc) buttonPress_cb, (void *)btnSpin);


/*  this callback is fired 5ms after the g_timeout_add() function above.
    It first sets the button state to ACTIVE to begin the animation cycle (pressed look)
    And then 250ms later calls buttonDePress_cb which will make the button look un-pressed
    and then send the button_clicked event.
*/    
gboolean buttonPress_cb( void *btn )
{

    gtk_widget_set_state((GtkWidget *)btn, GTK_STATE_ACTIVE);
    g_timeout_add(250, (GSourceFunc) buttonDePress_cb, btn);


    return( FALSE );
}

/*  Sets button state back to NORMAL ( not pressed look )
    and sends the button_clicked event so that the registered signal handler for the
    button can be activated
*/
gboolean buttonDePress_cb( void *btn )
{

    gtk_widget_set_state( btn, GTK_STATE_NORMAL);
    gtk_button_clicked( GTK_BUTTON( btn ));

    return( FALSE );
}
like image 425
Chimera Avatar asked Apr 25 '12 16:04

Chimera


2 Answers

There are several methods.

  1. Use XSendEvent. Caveat: some application frameworks ignore events sent with XSendEvent. I think Gtk+ doesn't, but I have not checked.
  2. Use XTestFakeMotionEvent and XTestFakeButtonEvent. You need XTest extension on your X server.
  3. Write a kernel driver for your device so that it will appear as a mouse/touchpad.
like image 54
n. 1.8e9-where's-my-share m. Avatar answered Sep 20 '22 17:09

n. 1.8e9-where's-my-share m.


The Linux input system has a facility for user-space implementation of input devices called uinput. You can write a background program that uses your device's callback library to send input events to the kernel. The X server (assuming it is using the evdev input module) would then process these just as any other mouse event.

There's a library called libsuinput that makes this fairly easy to do. It even includes an example mouse input program that you can probably use as a model. However, since your device is a touch-based device it will probably use absolute axes (ABS_X, ABS_Y) instead of relative (REL_X, REL_Y).

like image 43
Geoff Reedy Avatar answered Sep 23 '22 17:09

Geoff Reedy