From d00689120728d0bf0f7c3d65ec1d80470e76e10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 17 Jun 2013 21:54:38 -0400 Subject: [PATCH 1/2] xfreerdp: implement XInput 2.2 mouse pointer events --- client/X11/xf_event.c | 85 +++++++++++++++++++------------------------ client/X11/xf_event.h | 4 ++ client/X11/xf_input.c | 73 ++++++++++++++++++++++++++++--------- client/X11/xfreerdp.h | 1 + 4 files changed, 99 insertions(+), 64 deletions(-) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 77a24bd68..8c3f29fc9 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -130,32 +130,29 @@ static BOOL xf_event_VisibilityNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } -static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app) +BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app) { - int x, y; rdpInput* input; Window childWindow; input = xfc->instance->input; - x = event->xmotion.x; - y = event->xmotion.y; if (!xfc->settings->MouseMotion) { - if ((event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) == 0) + if ((state & (Button1Mask | Button2Mask | Button3Mask)) == 0) return TRUE; - } + } if (app) { /* make sure window exists */ - if (xf_rdpWindowFromWindow(xfc, event->xmotion.window) == 0) + if (xf_rdpWindowFromWindow(xfc, window) == 0) { return TRUE; } /* Translate to desktop coordinates */ - XTranslateCoordinates(xfc->display, event->xmotion.window, + XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y, &childWindow); } @@ -177,40 +174,38 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } -static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) +static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app) +{ + return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y, + event->xmotion.state, event->xmotion.window, app); +} + +BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app) { - int x, y; int flags; BOOL wheel; BOOL extended; rdpInput* input; Window childWindow; - input = xfc->instance->input; - - x = 0; - y = 0; flags = 0; wheel = FALSE; extended = FALSE; + input = xfc->instance->input; - switch (event->xbutton.button) + printf("ButtonPress: x: %d y: %d button: %d\n", x, y, button); + + switch (button) { case 1: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1; break; case 2: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3; break; case 3: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2; break; @@ -228,8 +223,6 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) case 8: /* back */ case 97: /* Xming */ extended = TRUE; - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1; break; @@ -237,8 +230,6 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) case 9: /* forward */ case 112: /* Xming */ extended = TRUE; - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2; break; @@ -260,12 +251,12 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) if (app) { /* make sure window exists */ - if (xf_rdpWindowFromWindow(xfc, event->xbutton.window) == 0) + if (xf_rdpWindowFromWindow(xfc, window) == 0) { return TRUE; } /* Translate to desktop coordinates */ - XTranslateCoordinates(xfc->display, event->xbutton.window, + XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y, &childWindow); } @@ -287,38 +278,36 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } -static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) +static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) +{ + return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y, + event->xbutton.button, event->xbutton.window, app); +} + +BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app) { - int x, y; int flags; + BOOL wheel; BOOL extended; rdpInput* input; Window childWindow; + flags = 0; + wheel = FALSE; + extended = FALSE; input = xfc->instance->input; - x = 0; - y = 0; - flags = 0; - extended = FALSE; - - switch (event->xbutton.button) + switch (button) { case 1: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_BUTTON1; break; case 2: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_BUTTON3; break; case 3: - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_FLAGS_BUTTON2; break; @@ -326,8 +315,6 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) case 8: case 97: extended = TRUE; - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_XFLAGS_BUTTON1; break; @@ -335,8 +322,6 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) case 9: case 112: extended = TRUE; - x = event->xbutton.x; - y = event->xbutton.y; flags = PTR_XFLAGS_BUTTON2; break; @@ -350,12 +335,12 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) if (app) { /* make sure window exists */ - if (xf_rdpWindowFromWindow(xfc, event->xbutton.window) == NULL) + if (xf_rdpWindowFromWindow(xfc, window) == NULL) { return TRUE; } /* Translate to desktop coordinates */ - XTranslateCoordinates(xfc->display, event->xbutton.window, + XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y, &childWindow); } @@ -376,6 +361,12 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } +static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) +{ + return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y, + event->xbutton.button, event->xbutton.window, app); +} + static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app) { KeySym keysym; diff --git a/client/X11/xf_event.h b/client/X11/xf_event.h index 4a6492f37..05d4e3e04 100644 --- a/client/X11/xf_event.h +++ b/client/X11/xf_event.h @@ -28,4 +28,8 @@ BOOL xf_event_process(freerdp* instance, XEvent* event); void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...); +BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app); +BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app); +BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app); + #endif /* __XF_EVENT_H */ diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 2cfffd922..a04bca96a 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -27,6 +27,8 @@ #include +#include "xf_event.h" + #include "xf_input.h" #ifdef WITH_XI @@ -63,7 +65,7 @@ int xf_input_init(xfContext* xfc, Window window) int minor = 2; Status xstatus; XIDeviceInfo* info; - XIEventMask evmasks[8]; + XIEventMask evmasks[64]; int opcode, event, error; BYTE masks[8][XIMaskLen(XI_LASTEVENT)]; @@ -88,6 +90,9 @@ int xf_input_init(xfContext* xfc, Window window) return -1; } + if (xfc->settings->MultiTouchInput) + xfc->use_xinput = TRUE; + info = XIQueryDevice(xfc->display, XIAllDevices, &ndevices); for (i = 0; i < ndevices; i++) @@ -99,28 +104,36 @@ int xf_input_init(xfContext* xfc, Window window) XIAnyClassInfo* class = dev->classes[j]; XITouchClassInfo* t = (XITouchClassInfo*) class; - if (class->type != XITouchClass) - continue; - - if (t->mode != XIDirectTouch) - continue; - - if (strcmp(dev->name, "Virtual core pointer") == 0) - continue; - - printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n", - dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", - dev->deviceid, t->mode, t->num_touches); + //printf("class->type: %d name: %s\n", class->type, dev->name); evmasks[nmasks].mask = masks[nmasks]; evmasks[nmasks].mask_len = sizeof(masks[0]); ZeroMemory(masks[nmasks], sizeof(masks[0])); evmasks[nmasks].deviceid = dev->deviceid; - XISetMask(masks[nmasks], XI_TouchBegin); - XISetMask(masks[nmasks], XI_TouchUpdate); - XISetMask(masks[nmasks], XI_TouchEnd); - nmasks++; + if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) && + (strcmp(dev->name, "Virtual core pointer") != 0)) + { + printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n", + dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", + dev->deviceid, t->mode, t->num_touches); + + XISetMask(masks[nmasks], XI_TouchBegin); + XISetMask(masks[nmasks], XI_TouchUpdate); + XISetMask(masks[nmasks], XI_TouchEnd); + nmasks++; + } + + if (xfc->use_xinput) + { + if (class->type == XIButtonClass) + { + XISetMask(masks[nmasks], XI_ButtonPress); + XISetMask(masks[nmasks], XI_ButtonRelease); + XISetMask(masks[nmasks], XI_Motion); + nmasks++; + } + } } } @@ -365,6 +378,31 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype) return 0; } +int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype) +{ + return TRUE; + + switch (evtype) + { + case XI_ButtonPress: + xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y, + event->detail, event->event, xfc->remote_app); + break; + + case XI_ButtonRelease: + xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y, + event->detail, event->event, xfc->remote_app); + break; + + case XI_Motion: + xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y, + event->detail, event->event, xfc->remote_app); + break; + } + + return 0; +} + int xf_input_handle_event_remote(xfContext* xfc, XEvent* event) { XGenericEventCookie* cookie = &event->xcookie; @@ -388,6 +426,7 @@ int xf_input_handle_event_remote(xfContext* xfc, XEvent* event) break; default: + xf_input_event(xfc, cookie->data, cookie->evtype); break; } } diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 802c9732f..37f187487 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -115,6 +115,7 @@ struct xf_context BOOL enableScaling; BOOL focused; + BOOL use_xinput; BOOL mouse_active; BOOL suppress_output; BOOL fullscreen_toggle; From 69e8d150e047e75611ae2d8492929a7a1af0af66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 17 Jun 2013 22:22:16 -0400 Subject: [PATCH 2/2] xfreerdp: improve multitouch debug output --- client/X11/xf_input.c | 46 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index a04bca96a..bf6601a9b 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -56,6 +56,22 @@ double z_vector; int xinput_opcode; int scale_cnt; +const char* xf_input_get_class_string(int class) +{ + if (class == XIKeyClass) + return "XIKeyClass"; + else if (class == XIButtonClass) + return "XIButtonClass"; + else if (class == XIValuatorClass) + return "XIValuatorClass"; + else if (class == XIScrollClass) + return "XIScrollClass"; + else if (class == XITouchClass) + return "XITouchClass"; + + return "XIUnknownClass"; +} + int xf_input_init(xfContext* xfc, Window window) { int i, j; @@ -97,6 +113,7 @@ int xf_input_init(xfContext* xfc, Window window) for (i = 0; i < ndevices; i++) { + BOOL touch = FALSE; XIDeviceInfo* dev = &info[i]; for (j = 0; j < dev->num_classes; j++) @@ -104,7 +121,24 @@ int xf_input_init(xfContext* xfc, Window window) XIAnyClassInfo* class = dev->classes[j]; XITouchClassInfo* t = (XITouchClassInfo*) class; - //printf("class->type: %d name: %s\n", class->type, dev->name); + if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) && + (strcmp(dev->name, "Virtual core pointer") != 0)) + { + touch = TRUE; + } + } + + for (j = 0; j < dev->num_classes; j++) + { + XIAnyClassInfo* class = dev->classes[j]; + XITouchClassInfo* t = (XITouchClassInfo*) class; + + if (xfc->settings->MultiTouchInput) + { + printf("%s (%d) \"%s\" id: %d\n", + xf_input_get_class_string(class->type), + class->type, dev->name, dev->deviceid); + } evmasks[nmasks].mask = masks[nmasks]; evmasks[nmasks].mask_len = sizeof(masks[0]); @@ -114,9 +148,12 @@ int xf_input_init(xfContext* xfc, Window window) if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) && (strcmp(dev->name, "Virtual core pointer") != 0)) { - printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n", + if (xfc->settings->MultiTouchInput) + { + printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n", dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", dev->deviceid, t->mode, t->num_touches); + } XISetMask(masks[nmasks], XI_TouchBegin); XISetMask(masks[nmasks], XI_TouchUpdate); @@ -126,7 +163,7 @@ int xf_input_init(xfContext* xfc, Window window) if (xfc->use_xinput) { - if (class->type == XIButtonClass) + if (!touch && (class->type == XIButtonClass)) { XISetMask(masks[nmasks], XI_ButtonPress); XISetMask(masks[nmasks], XI_ButtonRelease); @@ -385,16 +422,19 @@ int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype) switch (evtype) { case XI_ButtonPress: + printf("ButtonPress\n"); xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break; case XI_ButtonRelease: + printf("ButtonRelease\n"); xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break; case XI_Motion: + printf("Motion\n"); xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y, event->detail, event->event, xfc->remote_app); break;