channels/rdpei: fix long press (multitouch right-click)

This commit is contained in:
Marc-André Moreau 2013-06-11 16:15:46 -04:00
parent 404f66820b
commit 3317592ecb
3 changed files with 104 additions and 12 deletions

View File

@ -26,9 +26,12 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
@ -92,9 +95,15 @@ struct _RDPEI_PLUGIN
RDPINPUT_TOUCH_FRAME frame;
RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS];
RDPINPUT_CONTACT_POINT* contactPoints;
HANDLE mutex;
HANDLE event;
HANDLE thread;
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
int rdpei_send_frame(RdpeiClientContext* context);
const char* RDPEI_EVENTID_STRINGS[] =
{
"",
@ -106,6 +115,67 @@ const char* RDPEI_EVENTID_STRINGS[] =
"EVENTID_DISMISS_HOVERING_CONTACT"
};
int rdpei_add_frame(RdpeiClientContext* context)
{
int i;
RDPINPUT_CONTACT_DATA* contact;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
rdpei->frame.contactCount = 0;
for (i = 0; i < rdpei->maxTouchContacts; i++)
{
contact = (RDPINPUT_CONTACT_DATA*) &(rdpei->contactPoints[i].data);
if (rdpei->contactPoints[i].dirty)
{
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA));
rdpei->contactPoints[i].dirty = FALSE;
rdpei->frame.contactCount++;
}
else if (rdpei->contactPoints[i].active)
{
if (contact->contactFlags & CONTACT_FLAG_DOWN)
{
contact->contactFlags = CONTACT_FLAG_UPDATE;
contact->contactFlags |= CONTACT_FLAG_INRANGE;
contact->contactFlags |= CONTACT_FLAG_INCONTACT;
}
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA));
rdpei->frame.contactCount++;
}
}
return 1;
}
static void* rdpei_schedule_thread(void* arg)
{
DWORD status;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
while (1)
{
status = WaitForSingleObject(rdpei->event, 20);
WaitForSingleObject(rdpei->mutex, INFINITE);
rdpei_add_frame(context);
if (rdpei->frame.contactCount > 0)
rdpei_send_frame(context);
if (status == WAIT_OBJECT_0)
ResetEvent(rdpei->event);
ReleaseMutex(rdpei->mutex);
}
return NULL;
}
int rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, UINT32 pduLength)
{
int status;
@ -147,6 +217,13 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
Stream_SealLength(s);
if (!rdpei->thread)
{
rdpei->mutex = CreateMutex(NULL, FALSE, NULL);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpei_schedule_thread, (void*) rdpei, 0, NULL);
}
status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength);
Stream_Free(s, TRUE);
@ -180,7 +257,12 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
#endif
rdpei_write_2byte_unsigned(s, frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */
rdpei_write_8byte_unsigned(s, frame->frameOffset); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
/**
* the time offset from the previous frame (in microseconds).
* If this is the first frame being transmitted then this field MUST be set to zero.
*/
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
Stream_EnsureRemainingCapacity(s, frame->contactCount * 32);
@ -248,8 +330,13 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_
s = Stream_New(NULL, pduLength);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
rdpei_write_4byte_unsigned(s, frame->frameOffset); /* FOUR_BYTE_UNSIGNED_INTEGER */
rdpei_write_2byte_unsigned(s, 1); /* TWO_BYTE_UNSIGNED_INTEGER */
/**
* the time that has elapsed (in milliseconds) from when the oldest touch frame
* was generated to when it was encoded for transmission by the client.
*/
rdpei_write_4byte_unsigned(s, frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
rdpei_write_touch_frame(s, frame);
@ -443,15 +530,18 @@ int rdpei_send_frame(RdpeiClientContext* context)
int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact)
{
RDPINPUT_CONTACT_POINT* contactPoint;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
if (rdpei->frame.contactCount < MAX_CONTACTS)
{
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA));
rdpei->frame.contactCount++;
}
WaitForSingleObject(rdpei->mutex, INFINITE);
rdpei_send_frame(context);
contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[contact->contactId];
CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA));
contactPoint->dirty = TRUE;
SetEvent(rdpei->event);
ReleaseMutex(rdpei->mutex);
return 1;
}

View File

@ -88,11 +88,13 @@ struct _RDPINPUT_CONTACT_POINT
{
int lastX;
int lastY;
BOOL dirty;
BOOL active;
UINT32 state;
UINT32 flags;
UINT32 contactId;
int externalId;
RDPINPUT_CONTACT_DATA data;
};
typedef struct _RDPINPUT_CONTACT_POINT RDPINPUT_CONTACT_POINT;

View File

@ -341,17 +341,17 @@ int xf_input_touch_remote(xfInfo* xfi, XIDeviceEvent* event, int evtype)
if (evtype == XI_TouchBegin)
{
printf("TouchBegin: %d\n", touchId);
//printf("TouchBegin: %d\n", touchId);
contactId = rdpei->TouchBegin(rdpei, touchId, x, y);
}
else if (evtype == XI_TouchUpdate)
{
printf("TouchUpdate: %d\n", touchId);
//printf("TouchUpdate: %d\n", touchId);
contactId = rdpei->TouchUpdate(rdpei, touchId, x, y);
}
else if (evtype == XI_TouchEnd)
{
printf("TouchEnd: %d\n", touchId);
//printf("TouchEnd: %d\n", touchId);
contactId = rdpei->TouchEnd(rdpei, touchId, x, y);
}