mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
[client,common] common touch handling
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user