sending mouse events to another Xorg server

Matthias Apitz guru at unixarea.de
Fri May 5 06:19:04 UTC 2017


El día viernes, mayo 05, 2017 a las 01:39:59p. m. +1000, Peter Hutterer escribió:

> On Wed, May 03, 2017 at 07:23:38AM +0200, Matthias Apitz wrote:
> > 
> > I'm thinking in a X11-client running on the 2nd laptop
> > having a small grey window only (or even a tiny picture from
> > the TV's picture, but grey would be enough) and when the mouse
> > of the Xorg server enters this grey area, all mouse movements
> > and button clicks are populated to the Xorg and the 1st laptop
> > as the would have been done on its physical touchpad, something
> > like the xev(1) client, which protocols the mouse actions, in
> > the case of xev(1), to stdout.
> > 
> > Is there any way to do so?
> 
> look at synergy or x2x

Peter,

Thanks for the pointer to 'synergy'. I watched some video on its home
page and it looks pretty cool.

Yesterday I hacked down, based on the source of X11' xev(1) application,
some first testclient which also worked and let me last night crontrol
the firefox live streams on the remote host and on its connected TV
screen. Just for the records, it goes mostely like this:

from the modified xev.c:

...
Display *dpy;
Display *rdpy;        /* the remote display, i.e. the remote TV */

/* TV-control implemented 'xtele' (based on X11' xev(1))
 *
 * the idea: control from some laptop screen (1366x768) the full screen
 * application running on the external VGA display of some other laptop; the
 * picture is like this:
 *
 * +--------------------+      +--------------------++--------------------+
 * |                    |      |                    ||                    |
 * |                    |      |                    ||                    |
 * |    1366 x 768      |=====>|   1366 x 768       ||     1920 x 1080    |
 * |                    |      |       LCD1         ||         VGA1       |
 * |                    |      |                    ||                    |
 * +--------------------+      +--------------------+|                    |
 *                                                   |                    |
 *                                                   |                    |
 *                                                   +--------------------+
 *
 * this means:
 * - we must map the area 1366x768 to 1920x1080, i.e. by a RATIO of 1.4
 * - we must right shift the X,Y by adding a SHIFT of 1366 to X value
 * - note: the controlling app 'xtele' has an upper border of 20 px, added by the
 *   local window manager; so we must add a an UP shift of -20 px  
 *   XXX: can we still reach the TV controls at the button of a full screen running?
 */

#define RATIO 1.4
#define SHIFT 1366
#define UP    20

...



static void
do_KeyPress (XEvent *eventp)
{
    XKeyEvent *e = (XKeyEvent *) eventp;

    /* TV-control implemented */

    /* Fake the XTestFakeKeyEvent in the current position */
    printf("Button %s\n", e->state == 0x00 ? "Pressed" : "Released");

    XTestFakeKeyEvent (rdpy, e->keycode, e->type == KeyPress ? True : False, CurrentTime);
    XSync(rdpy, 0);

}

static void
do_KeyRelease (XEvent *eventp)
{
    do_KeyPress (eventp);		/* since it has the same info */
}

static void
do_ButtonPress (XEvent *eventp)
{
    XButtonEvent *e = (XButtonEvent *) eventp;

    /* TV-control implemented */

    /* Fake the XTestFakeButtonEvent in the current position */
    printf("Button %s\n", e->state == 0x00 ? "Pressed" : "Released");
    XTestFakeButtonEvent (rdpy, e->button, e->state == 0x00 ? True : False, CurrentTime);
    XSync(rdpy, 0);

}

static void
do_ButtonRelease (XEvent *eventp)
{
    do_ButtonPress (eventp);		/* since it has the same info */
}

static void
do_MotionNotify (XEvent *eventp)
{

    /* TV-control implemented */

    XMotionEvent *e = (XMotionEvent *) eventp;
    int newX = (e->x_root)*RATIO + SHIFT;
    int newY = (e->y_root)*RATIO - UP;
   
    /* Fake the pointer movement to new absolute position */
    printf("moved to root(%d, %d)\n", newX, newY);
    XTestFakeMotionEvent (rdpy, 0, newX, newY, CurrentTime);
    XSync(rdpy, 0);

}

...

the app has a new arg '-tele host:dpy' which is opened as a 2nd
XOpenDisplay():

int
main (int argc, char **argv)
{
    char *displayname = NULL;
    char *rdisplayname = NULL;
    char *geom = NULL;
    ...

	if (arg[0] == '-') {
	    switch (arg[1]) {
	      case 't':			/* -tele host:dpy */
		if (++i >= argc) usage ("-display requires an argument");
		rdisplayname = argv[i];
		continue;
		...

    dpy = XOpenDisplay (displayname);
    if (!dpy) {
	fprintf (stderr, "%s:  unable to open display '%s'\n",
		 ProgramName, XDisplayName (displayname));
	exit (1);
    }

    /* connect to the remote TV screen */

    rdpy = XOpenDisplay (rdisplayname);
    if (!rdpy) {
	fprintf (stderr, "%s:  unable to open display '%s'\n",
		 ProgramName, XDisplayName (rdisplayname));
	exit (1);
    }

Cool! :-)

-- 
Matthias Apitz, ✉ guru at unixarea.de, ⌂ http://www.unixarea.de/  ☎ +49-176-38902045


More information about the xorg mailing list