Extended AINPUT API:

* Each event now has a timestamp
* Relative and absolute events are sent simultaneously
* Added a flag indicating relative events are available
This commit is contained in:
Armin Novak 2022-01-26 14:21:53 +01:00 committed by akallabeth
parent e136444f51
commit f03059e718
13 changed files with 50 additions and 36 deletions

View File

@ -28,6 +28,7 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/assert.h> #include <winpr/assert.h>
#include <winpr/stream.h> #include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include "ainput_main.h" #include "ainput_main.h"
#include <freerdp/channels/log.h> #include <freerdp/channels/log.h>
@ -111,12 +112,14 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags,
AINPUT_PLUGIN* ainput; AINPUT_PLUGIN* ainput;
AINPUT_CHANNEL_CALLBACK* callback; AINPUT_CHANNEL_CALLBACK* callback;
BYTE buffer[32] = { 0 }; BYTE buffer[32] = { 0 };
UINT64 time;
wStream sbuffer = { 0 }; wStream sbuffer = { 0 };
wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer)); wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
WINPR_ASSERT(s); WINPR_ASSERT(s);
WINPR_ASSERT(context); WINPR_ASSERT(context);
time = GetTickCount64();
ainput = (AINPUT_PLUGIN*)context->handle; ainput = (AINPUT_PLUGIN*)context->handle;
WINPR_ASSERT(ainput); WINPR_ASSERT(ainput);
WINPR_ASSERT(ainput->listener_callback); WINPR_ASSERT(ainput->listener_callback);
@ -132,14 +135,15 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags,
{ {
char buffer[128] = { 0 }; char buffer[128] = { 0 };
WLog_VRB(TAG, "[%s] sending flags=%s, %" PRId32 "x%" PRId32, __FUNCTION__, WLog_VRB(TAG, "[%s] sending timestamp=0x%08" PRIx64 ", flags=%s, %" PRId32 "x%" PRId32,
ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y); __FUNCTION__, time, ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y);
} }
/* Message type */ /* Message type */
Stream_Write_UINT16(s, MSG_AINPUT_MOUSE); Stream_Write_UINT16(s, MSG_AINPUT_MOUSE);
/* Event data */ /* Event data */
Stream_Write_UINT64(s, time);
Stream_Write_UINT64(s, flags); Stream_Write_UINT64(s, flags);
Stream_Write_INT32(s, x); Stream_Write_INT32(s, x);
Stream_Write_INT32(s, y); Stream_Write_INT32(s, y);

View File

@ -50,6 +50,8 @@ static INLINE const char* ainput_flags_to_string(UINT64 flags, char* buffer, siz
{ {
char number[32] = { 0 }; char number[32] = { 0 };
if (flags & AINPUT_FLAGS_HAVE_REL)
ainput_append(buffer, size, "AINPUT_FLAGS_HAVE_REL", TRUE);
if (flags & AINPUT_FLAGS_WHEEL) if (flags & AINPUT_FLAGS_WHEEL)
ainput_append(buffer, size, "AINPUT_FLAGS_WHEEL", TRUE); ainput_append(buffer, size, "AINPUT_FLAGS_WHEEL", TRUE);
if (flags & AINPUT_FLAGS_MOVE) if (flags & AINPUT_FLAGS_MOVE)

View File

@ -146,23 +146,24 @@ static UINT ainput_server_send_version(ainput_server* ainput, wStream* s)
static UINT ainput_server_recv_mouse_event(ainput_server* ainput, wStream* s) static UINT ainput_server_recv_mouse_event(ainput_server* ainput, wStream* s)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
UINT64 flags; UINT64 flags, time;
INT32 x, y; INT32 x, y;
char buffer[128] = { 0 }; char buffer[128] = { 0 };
WINPR_ASSERT(ainput); WINPR_ASSERT(ainput);
WINPR_ASSERT(s); WINPR_ASSERT(s);
if (Stream_GetRemainingLength(s) < 16) if (Stream_GetRemainingLength(s) < 24)
return ERROR_NO_DATA; return ERROR_NO_DATA;
Stream_Read_UINT64(s, time);
Stream_Read_UINT64(s, flags); Stream_Read_UINT64(s, flags);
Stream_Read_INT32(s, x); Stream_Read_INT32(s, x);
Stream_Read_INT32(s, y); Stream_Read_INT32(s, y);
WLog_VRB(TAG, "[%s] received: flags=%s, %" PRId32 "x%" PRId32, __FUNCTION__, WLog_VRB(TAG, "[%s] received: time=0x%08" PRIx64 ", flags=%s, %" PRId32 "x%" PRId32,
ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y); __FUNCTION__, time, ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y);
IFCALLRET(ainput->context.MouseEvent, error, &ainput->context, flags, x, y); IFCALLRET(ainput->context.MouseEvent, error, &ainput->context, time, flags, x, y);
return error; return error;
} }

View File

@ -445,7 +445,7 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOO
{ {
WINPR_ASSERT(xfc); WINPR_ASSERT(xfc);
if (xfc->xi_event || xfc->xi_rawevent) if (xfc->xi_event)
return TRUE; return TRUE;
if (xfc->window) if (xfc->window)
@ -534,7 +534,7 @@ static BOOL xf_grab_mouse(xfContext* xfc)
ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask |
EnterWindowMask | LeaveWindowMask, EnterWindowMask | LeaveWindowMask,
GrabModeAsync, GrabModeAsync, xfc->window->handle, None, CurrentTime); GrabModeAsync, GrabModeAsync, xfc->window->handle, None, CurrentTime);
xfc->mouse_grabbed = TRUE; xfc->common.mouse_grabbed = TRUE;
} }
return TRUE; return TRUE;
} }
@ -554,7 +554,7 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, const XButtonEvent* event, BOOL
{ {
xf_grab_mouse(xfc); xf_grab_mouse(xfc);
if (xfc->xi_event || xfc->xi_rawevent) if (xfc->xi_event)
return TRUE; return TRUE;
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app, TRUE); return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app, TRUE);
} }
@ -563,7 +563,7 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, const XButtonEvent* event, BO
{ {
xf_grab_mouse(xfc); xf_grab_mouse(xfc);
if (xfc->xi_event || xfc->xi_rawevent) if (xfc->xi_event)
return TRUE; return TRUE;
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app, return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app,
FALSE); FALSE);

View File

@ -648,27 +648,24 @@ int xf_input_event(xfContext* xfc, const XEvent* xevent, XIDeviceEvent* event, i
{ {
case XI_ButtonPress: case XI_ButtonPress:
xfc->xi_event = TRUE; xfc->xi_event = TRUE;
if (!xfc->xi_rawevent)
xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail, xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail,
event->event, xfc->remote_app, TRUE); event->event, xfc->remote_app, TRUE);
break; break;
case XI_ButtonRelease: case XI_ButtonRelease:
xfc->xi_event = TRUE; xfc->xi_event = TRUE;
if (!xfc->xi_rawevent)
xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail, xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail,
event->event, xfc->remote_app, FALSE); event->event, xfc->remote_app, FALSE);
break; break;
case XI_Motion: case XI_Motion:
xfc->xi_event = TRUE; xfc->xi_event = TRUE;
if (!xfc->xi_rawevent)
xf_generic_MotionNotify(xfc, (int)event->event_x, (int)event->event_y, xf_generic_MotionNotify(xfc, (int)event->event_x, (int)event->event_y,
event->detail, event->event, xfc->remote_app); event->detail, event->event, xfc->remote_app);
break; break;
case XI_RawButtonPress: case XI_RawButtonPress:
case XI_RawButtonRelease: case XI_RawButtonRelease:
xfc->xi_rawevent = xfc->mouse_grabbed && xfc->xi_rawevent = xfc->common.mouse_grabbed &&
freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove); freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove);
if (xfc->xi_rawevent) if (xfc->xi_rawevent)
@ -679,7 +676,7 @@ int xf_input_event(xfContext* xfc, const XEvent* xevent, XIDeviceEvent* event, i
} }
break; break;
case XI_RawMotion: case XI_RawMotion:
xfc->xi_rawevent = xfc->mouse_grabbed && xfc->xi_rawevent = xfc->common.mouse_grabbed &&
freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove); freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove);
if (xfc->xi_rawevent) if (xfc->xi_rawevent)

View File

@ -437,7 +437,7 @@ void xf_keyboard_focus_in(xfContext* xfc)
if (XQueryPointer(xfc->display, xfc->window->handle, &w, &w, &d, &d, &x, &y, &state)) if (XQueryPointer(xfc->display, xfc->window->handle, &w, &w, &d, &d, &x, &y, &state))
{ {
if (x >= 0 && x < xfc->window->width && y >= 0 && y < xfc->window->height) if ((x >= 0) && (x < xfc->window->width) && (y >= 0) && (y < xfc->window->height))
{ {
xf_event_adjust_coordinates(xfc, &x, &y); xf_event_adjust_coordinates(xfc, &x, &y);
freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_MOVE, x, y); freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_MOVE, x, y);
@ -733,5 +733,5 @@ BOOL xf_ungrab(xfContext* xfc)
WINPR_ASSERT(xfc); WINPR_ASSERT(xfc);
XUngrabKeyboard(xfc->display, CurrentTime); XUngrabKeyboard(xfc->display, CurrentTime);
XUngrabPointer(xfc->display, CurrentTime); XUngrabPointer(xfc->display, CurrentTime);
xfc->mouse_grabbed = FALSE; xfc->common.mouse_grabbed = FALSE;
} }

View File

@ -300,8 +300,6 @@ struct xf_context
#endif #endif
BOOL xi_rawevent; BOOL xi_rawevent;
BOOL xi_event; BOOL xi_event;
BOOL mouse_grabbed;
}; };
BOOL xf_create_window(xfContext* xfc); BOOL xf_create_window(xfContext* xfc);

View File

@ -1088,9 +1088,15 @@ BOOL freerdp_client_send_button_event(rdpClientContext* cctx, BOOL relative, UIN
if (cctx->ainput) if (cctx->ainput)
{ {
UINT64 flags = 0; UINT64 flags = 0;
BOOL relativeInput =
freerdp_settings_get_bool(cctx->context.settings, FreeRDP_MouseUseRelativeMove);
if (cctx->mouse_grabbed && relativeInput)
flags |= AINPUT_FLAGS_HAVE_REL;
if (relative) if (relative)
flags |= AINPUT_FLAGS_REL; flags |= AINPUT_FLAGS_REL;
if (mflags & PTR_FLAGS_DOWN) if (mflags & PTR_FLAGS_DOWN)
flags |= AINPUT_FLAGS_DOWN; flags |= AINPUT_FLAGS_DOWN;
if (mflags & PTR_FLAGS_BUTTON1) if (mflags & PTR_FLAGS_BUTTON1)

View File

@ -41,6 +41,7 @@ typedef enum
AINPUT_FLAGS_DOWN = 0x0008, AINPUT_FLAGS_DOWN = 0x0008,
AINPUT_FLAGS_REL = 0x0010, AINPUT_FLAGS_REL = 0x0010,
AINPUT_FLAGS_HAVE_REL = 0x0020,
/* Pointer Flags */ /* Pointer Flags */
AINPUT_FLAGS_BUTTON1 = 0x1000, /* left */ AINPUT_FLAGS_BUTTON1 = 0x1000, /* left */

View File

@ -83,20 +83,21 @@ extern "C"
rdpContext context; rdpContext context;
ALIGN64 HANDLE thread; /**< (offset 0) */ ALIGN64 HANDLE thread; /**< (offset 0) */
#if defined(CHANNEL_AINPUT_CLIENT) #if defined(CHANNEL_AINPUT_CLIENT)
ALIGN64 AInputClientContext* ainput; /**< (offset 1) */ ALIGN64 AInputClientContext* ainput; /**< (offset 1) */
#else #else
UINT64 reserved1; UINT64 reserved1;
#endif #endif
#if defined(CHANNEL_RDPEI_CLIENT) #if defined(CHANNEL_RDPEI_CLIENT)
ALIGN64 RdpeiClientContext* rdpei; /**< (offset 2) */ ALIGN64 RdpeiClientContext* rdpei; /**< (offset 2) */
#else #else
UINT64 reserved2; UINT64 reserved2;
#endif #endif
ALIGN64 INT32 lastX; /**< (offset 3) */ ALIGN64 INT32 lastX; /**< (offset 3) */
ALIGN64 INT32 lastY; /**< (offset 4) */ ALIGN64 INT32 lastY; /**< (offset 4) */
UINT64 reserved[128 - 5]; /**< (offset 5) */ ALIGN64 BOOL mouse_grabbed; /** < (offset 5) */
UINT64 reserved[128 - 6]; /**< (offset 6) */
}; };
/* Common client functions */ /* Common client functions */
@ -141,9 +142,9 @@ extern "C"
char** username, char** password, char** username, char** password,
char** domain)); char** domain));
FREERDP_API FREERDP_API
WINPR_DEPRECATED_VAR("Use client_cli_authenticate_ex", WINPR_DEPRECATED_VAR("Use client_cli_authenticate_ex",
BOOL client_cli_gw_authenticate(freerdp* instance, char** username, BOOL client_cli_gw_authenticate(freerdp* instance, char** username,
char** password, char** domain)); char** password, char** domain));
FREERDP_API WINPR_DEPRECATED_VAR( FREERDP_API WINPR_DEPRECATED_VAR(
"Use client_cli_verify_certificate_ex", "Use client_cli_verify_certificate_ex",
@ -182,6 +183,9 @@ extern "C"
FREERDP_API BOOL freerdp_client_send_wheel_event(rdpClientContext* cctx, UINT16 mflags); FREERDP_API BOOL freerdp_client_send_wheel_event(rdpClientContext* cctx, UINT16 mflags);
FREERDP_API BOOL freerdp_client_send_mouse_event(rdpClientContext* cctx, UINT64 mflags, INT32 x,
INT32 y);
FREERDP_API BOOL freerdp_client_send_button_event(rdpClientContext* cctx, BOOL relative, FREERDP_API BOOL freerdp_client_send_button_event(rdpClientContext* cctx, BOOL relative,
UINT16 mflags, INT32 x, INT32 y); UINT16 mflags, INT32 x, INT32 y);

View File

@ -40,8 +40,8 @@ typedef BOOL (*psAInputServerIsOpen)(ainput_server_context* context);
typedef UINT (*psAInputServerOpenResult)(ainput_server_context* context, typedef UINT (*psAInputServerOpenResult)(ainput_server_context* context,
AINPUT_SERVER_OPEN_RESULT result); AINPUT_SERVER_OPEN_RESULT result);
typedef UINT (*psAInputServerMouseEvent)(ainput_server_context* context, UINT64 flags, INT32 x, typedef UINT (*psAInputServerMouseEvent)(ainput_server_context* context, UINT64 timestamp,
INT32 y); UINT64 flags, INT32 x, INT32 y);
struct _ainput_server_context struct _ainput_server_context
{ {

View File

@ -15,7 +15,7 @@ WITH_OPENSSL=1
WITH_FFMPEG=0 WITH_FFMPEG=0
BUILD_DEPS=1 BUILD_DEPS=1
DEPS_ONLY=0 DEPS_ONLY=0
NDK_TARGET=26 NDK_TARGET=23
JPEG_TAG=master JPEG_TAG=master
OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0 OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0
@ -23,7 +23,8 @@ OPENSSL_TAG=OpenSSL_1_1_1m
FFMPEG_TAG=n4.4.1 FFMPEG_TAG=n4.4.1
SRC_DIR=$SCRIPT_PATH/.. SRC_DIR=$SCRIPT_PATH/..
BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs #BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs
BUILD_DST=~/StudioProjects/tcclient-android/app/libs/
BUILD_SRC=$SRC_DIR/build BUILD_SRC=$SRC_DIR/build
CMAKE_BUILD_TYPE=Debug CMAKE_BUILD_TYPE=Debug

View File

@ -40,14 +40,14 @@
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
static UINT sf_peer_ainput_mouse_event(ainput_server_context* context, UINT64 flags, INT32 x, static UINT sf_peer_ainput_mouse_event(ainput_server_context* context, UINT64 timestamp,
INT32 y) UINT64 flags, INT32 x, INT32 y)
{ {
/* TODO: Implement */ /* TODO: Implement */
WINPR_ASSERT(context); WINPR_ASSERT(context);
WLog_WARN(TAG, "%s not implemented: 0x%08" PRIx64 ", %" PRId32 "x%" PRId32, __FUNCTION__, flags, WLog_WARN(TAG, "%s not implemented: 0x%08" PRIx64 ", 0x%08" PRIx64 ", %" PRId32 "x%" PRId32,
x, y); __FUNCTION__, timestamp, flags, x, y);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }