[client,common] common touch handling

This commit is contained in:
Armin Novak
2022-12-30 19:07:46 +01:00
committed by akallabeth
parent 08ffe661e0
commit d66b165b8e
5 changed files with 235 additions and 181 deletions

View File

@@ -396,197 +396,57 @@ BOOL wlf_keyboard_modifiers(freerdp* instance, const UwacKeyboardModifiersEvent*
BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev)
{
int32_t x = 0, y = 0;
size_t i;
int touchId;
int32_t x, y;
wlfContext* wlf;
if (!instance || !ev || !instance->context)
return FALSE;
WINPR_ASSERT(instance);
WINPR_ASSERT(ev);
wlf = instance->context;
WINPR_ASSERT(wlf);
wlf = (wlfContext*)instance->context;
touchId = ev->id;
for (i = 0; i < MAX_CONTACTS; i++)
{
touchContact* contact = &wlf->contacts[i];
if (contact->id == touchId)
{
contact->id = 0;
x = (int32_t)contact->pos_x;
y = (int32_t)contact->pos_y;
break;
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
x = ev->x;
y = ev->y;
if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
return FALSE;
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = wlf->common.rdpei;
if (wlf->contacts[i].emulate_mouse == TRUE)
{
UINT16 flags = 0;
flags |= PTR_FLAGS_BUTTON1;
WINPR_ASSERT(x <= UINT16_MAX);
WINPR_ASSERT(y <= UINT16_MAX);
return freerdp_client_send_button_event(&wlf->common, FALSE, flags, x, y);
}
if (!rdpei)
return FALSE;
{
int contactId;
WINPR_ASSERT(rdpei->TouchEnd);
rdpei->TouchEnd(rdpei, touchId, x, y, &contactId);
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_UP, ev->id,0, x, y);
}
BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev)
{
int32_t x, y;
int i;
int touchId;
wlfContext* wlf;
if (!instance || !ev || !instance->context)
return FALSE;
wlf = (wlfContext*)instance->context;
WINPR_ASSERT(instance);
WINPR_ASSERT(ev);
wlf = instance->context;
WINPR_ASSERT(wlf);
x = ev->x;
y = ev->y;
touchId = ev->id;
for (i = 0; i < MAX_CONTACTS; i++)
{
if (wlf->contacts[i].id == 0)
{
wlf->contacts[i].id = touchId;
wlf->contacts[i].pos_x = x;
wlf->contacts[i].pos_y = y;
wlf->contacts[i].emulate_mouse = FALSE;
break;
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
return FALSE;
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = wlf->common.rdpei;
// Emulate mouse click if touch is not possible, like in login screen
if (!rdpei)
{
wlf->contacts[i].emulate_mouse = TRUE;
UINT16 flags = 0;
flags |= PTR_FLAGS_DOWN;
flags |= PTR_FLAGS_MOVE;
flags |= PTR_FLAGS_BUTTON1;
WINPR_ASSERT(x <= UINT16_MAX);
WINPR_ASSERT(y <= UINT16_MAX);
return freerdp_client_send_button_event(&wlf->common, FALSE, flags, x, y);
}
WINPR_ASSERT(rdpei);
{
int contactId;
WINPR_ASSERT(rdpei->TouchBegin);
rdpei->TouchBegin(rdpei, touchId, x, y, &contactId);
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_DOWN, ev->id, 0,x, y);
}
BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev)
{
int32_t x, y;
int i;
int touchId;
wlfContext* wlf;
if (!instance || !ev || !instance->context)
return FALSE;
wlf = (wlfContext*)instance->context;
WINPR_ASSERT(instance);
WINPR_ASSERT(ev);
wlf = instance->context;
WINPR_ASSERT(wlf);
x = ev->x;
y = ev->y;
touchId = ev->id;
for (i = 0; i < MAX_CONTACTS; i++)
{
if (wlf->contacts[i].id == touchId)
{
if ((fabs(wlf->contacts[i].pos_x - x) < DBL_EPSILON) &&
(fabs(wlf->contacts[i].pos_y - y) < DBL_EPSILON))
{
return TRUE;
}
wlf->contacts[i].pos_x = x;
wlf->contacts[i].pos_y = y;
break;
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
return FALSE;
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = ((wlfContext*)instance->context)->common.rdpei;
if (wlf->contacts[i].emulate_mouse == TRUE)
{
UINT16 flags = 0;
flags |= PTR_FLAGS_MOVE;
WINPR_ASSERT(x <= UINT16_MAX);
WINPR_ASSERT(y <= UINT16_MAX);
return freerdp_client_send_button_event(&wlf->common, FALSE, flags, x, y);
}
if (!rdpei)
return FALSE;
{
int contactId;
WINPR_ASSERT(rdpei->TouchUpdate);
rdpei->TouchUpdate(rdpei, touchId, x, y, &contactId);
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_MOTION,0, ev->id, x, y);
}

View File

@@ -30,16 +30,6 @@
typedef struct wlf_clipboard wfClipboard;
typedef struct s_wlfDispContext wlfDispContext;
#define MAX_CONTACTS 20
typedef struct
{
int id;
double pos_x;
double pos_y;
BOOL emulate_mouse;
} touchContact;
typedef struct
{
rdpClientContext common;
@@ -59,8 +49,6 @@ typedef struct
wLog* log;
CRITICAL_SECTION critical;
wArrayList* events;
touchContact contacts[MAX_CONTACTS];
} wlfContext;
BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP);

View File

@@ -189,7 +189,6 @@ int xf_input_init(xfContext* xfc, Window window)
settings = xfc->common.context.settings;
WINPR_ASSERT(settings);
memset(xfc->contacts, 0, sizeof(xfc->contacts));
xfc->firstDist = -1.0;
xfc->z_vector = 0;
xfc->px_vector = 0;
@@ -596,7 +595,6 @@ static int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtyp
{
int x, y;
int touchId;
int contactId;
RdpeiClientContext* rdpei = xfc->common.rdpei;
if (!rdpei)
@@ -611,16 +609,13 @@ static int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtyp
switch (evtype)
{
case XI_TouchBegin:
WLog_DBG(TAG, "TouchBegin: %d", touchId);
rdpei->TouchBegin(rdpei, touchId, x, y, &contactId);
freerdp_client_handle_touch(&xfc->common, FREERDP_TOUCH_DOWN, touchId, x, y);
break;
case XI_TouchUpdate:
WLog_DBG(TAG, "TouchUpdate: %d", touchId);
rdpei->TouchUpdate(rdpei, touchId, x, y, &contactId);
freerdp_client_handle_touch(&xfc->common, FREERDP_TOUCH_MOTION, touchId, x, y);
break;
case XI_TouchEnd:
WLog_DBG(TAG, "TouchEnd: %d", touchId);
rdpei->TouchEnd(rdpei, touchId, x, y, &contactId);
freerdp_client_handle_touch(&xfc->common, FREERDP_TOUCH_UP, touchId, x, y);
break;
default:
break;

View File

@@ -21,6 +21,8 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <float.h>
#include <freerdp/client.h>
@@ -1358,6 +1360,192 @@ BOOL freerdp_client_send_extended_button_event(rdpClientContext* cctx, BOOL rela
return TRUE;
}
static BOOL freerdp_handle_touch_up(rdpClientContext* cctx, const FreeRDP_TouchContact* contact)
{
WINPR_ASSERT(cctx);
WINPR_ASSERT(contact);
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = cctx->rdpei;
if (!rdpei)
{
UINT16 flags = 0;
flags |= PTR_FLAGS_BUTTON1;
WINPR_ASSERT(contact->x <= UINT16_MAX);
WINPR_ASSERT(contact->y <= UINT16_MAX);
return freerdp_client_send_button_event(cctx, FALSE, flags, contact->x, contact->y);
}
else
{
int contactId;
if (rdpei->TouchRawEvent)
{
const UINT32 flags = RDPINPUT_CONTACT_FLAG_UP;
const UINT32 contactFlags = ((contact->flags & FREERDP_TOUCH_HAS_PRESSURE) != 0)
? CONTACT_DATA_PRESSURE_PRESENT
: 0;
rdpei->TouchRawEvent(rdpei, contact->id, contact->x, contact->y, &contactId, flags,
contactFlags, contact->pressure);
}
else
{
WINPR_ASSERT(rdpei->TouchEnd);
rdpei->TouchEnd(rdpei, contact->id, contact->x, contact->y, &contactId);
}
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
}
static BOOL freerdp_handle_touch_down(rdpClientContext* cctx, const FreeRDP_TouchContact* contact)
{
WINPR_ASSERT(cctx);
WINPR_ASSERT(contact);
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = cctx->rdpei;
// Emulate mouse click if touch is not possible, like in login screen
if (!rdpei)
{
UINT16 flags = 0;
flags |= PTR_FLAGS_DOWN;
flags |= PTR_FLAGS_MOVE;
flags |= PTR_FLAGS_BUTTON1;
WINPR_ASSERT(contact->x <= UINT16_MAX);
WINPR_ASSERT(contact->y <= UINT16_MAX);
return freerdp_client_send_button_event(cctx, FALSE, flags, contact->x, contact->y);
}
else
{
int contactId;
if (rdpei->TouchRawEvent)
{
const UINT32 flags = RDPINPUT_CONTACT_FLAG_DOWN;
const UINT32 contactFlags = ((contact->flags & FREERDP_TOUCH_HAS_PRESSURE) != 0)
? CONTACT_DATA_PRESSURE_PRESENT
: 0;
rdpei->TouchRawEvent(rdpei, contact->id, contact->x, contact->y, &contactId, flags,
contactFlags, contact->pressure);
}
else
{
WINPR_ASSERT(rdpei->TouchBegin);
rdpei->TouchBegin(rdpei, contact->id, contact->x, contact->y, &contactId);
}
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
}
static BOOL freerdp_handle_touch_motion(rdpClientContext* cctx, const FreeRDP_TouchContact* contact)
{
WINPR_ASSERT(cctx);
WINPR_ASSERT(contact);
#if defined(CHANNEL_RDPEI_CLIENT)
RdpeiClientContext* rdpei = cctx->rdpei;
if (!rdpei)
{
UINT16 flags = 0;
flags |= PTR_FLAGS_MOVE;
WINPR_ASSERT(contact->x <= UINT16_MAX);
WINPR_ASSERT(contact->y <= UINT16_MAX);
return freerdp_client_send_button_event(cctx, FALSE, flags, contact->x, contact->y);
}
else
{
int contactId;
if (rdpei->TouchRawEvent)
{
const UINT32 flags = RDPINPUT_CONTACT_FLAG_UPDATE;
const UINT32 contactFlags = ((contact->flags & FREERDP_TOUCH_HAS_PRESSURE) != 0)
? CONTACT_DATA_PRESSURE_PRESENT
: 0;
rdpei->TouchRawEvent(rdpei, contact->id, contact->x, contact->y, &contactId, flags,
contactFlags, contact->pressure);
}
else
{
WINPR_ASSERT(rdpei->TouchUpdate);
rdpei->TouchUpdate(rdpei, contact->id, contact->x, contact->y, &contactId);
}
}
#else
WLog_WARN(TAG, "Touch event detected but RDPEI support not compiled in. Recompile with "
"-DWITH_CHANNELS=ON");
#endif
return TRUE;
}
static BOOL freerdp_client_touch_update(rdpClientContext* cctx, UINT32 flags, INT32 touchId,
UINT32 pressure, INT32 x, INT32 y,
const FreeRDP_TouchContact** ppcontact)
{
WINPR_ASSERT(cctx);
WINPR_ASSERT(ppcontact);
for (size_t i = 0; i < ARRAYSIZE(cctx->contacts); i++)
{
FreeRDP_TouchContact* contact = &cctx->contacts[i];
if (contact->id == touchId)
{
*ppcontact = contact;
contact->flags = flags;
contact->pressure = pressure;
contact->x = x;
contact->y = y;
return TRUE;
}
}
return FALSE;
}
BOOL freerdp_client_handle_touch(rdpClientContext* cctx, UINT32 flags, INT32 finger,
UINT32 pressure, INT32 x, INT32 y)
{
WINPR_ASSERT(cctx);
const FreeRDP_TouchContact* contact = NULL;
if (!freerdp_client_touch_update(cctx, flags, finger, pressure, x, y, &contact))
return FALSE;
switch (flags)
{
case FREERDP_TOUCH_DOWN:
return freerdp_handle_touch_down(cctx, contact);
case FREERDP_TOUCH_UP:
return freerdp_handle_touch_up(cctx, contact);
case FREERDP_TOUCH_MOTION:
return freerdp_handle_touch_motion(cctx, contact);
default:
WLog_WARN(TAG, "Unhandled FreeRDPTouchEventType %d, ignoring", flags);
return FALSE;
}
}
BOOL freerdp_client_load_channels(freerdp* instance)
{
WINPR_ASSERT(instance);

View File

@@ -79,6 +79,17 @@ extern "C"
typedef int (*pRdpClientEntry)(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
/* Common Client Interface */
#define FREERDP_MAX_TOUCH_CONTACTS 10
typedef struct
{
ALIGN64 INT32 id;
ALIGN64 UINT32 count;
ALIGN64 INT32 x;
ALIGN64 INT32 y;
ALIGN64 UINT32 flags;
ALIGN64 UINT32 pressure;
} FreeRDP_TouchContact;
struct rdp_client_context
{
@@ -106,7 +117,8 @@ extern "C"
#else
UINT64 reserved3[2];
#endif
UINT64 reserved[128 - 8]; /**< (offset 8) */
ALIGN64 FreeRDP_TouchContact contacts[FREERDP_MAX_TOUCH_CONTACTS]; /**< (offset 8) */
UINT64 reserved[128 - 68]; /**< (offset 68) */
};
/* Common client functions */
@@ -193,6 +205,17 @@ extern "C"
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
BOOL (*window_events)(freerdp* instance));
typedef enum
{
FREERDP_TOUCH_DOWN = 0x01,
FREERDP_TOUCH_UP = 0x02,
FREERDP_TOUCH_MOTION = 0x04,
FREERDP_TOUCH_HAS_PRESSURE = 0x100
} FreeRDPTouchEventType;
FREERDP_API BOOL freerdp_client_handle_touch(rdpClientContext* cctx, UINT32 flags, INT32 finger,
UINT32 pressure, INT32 x, INT32 y);
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,