diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index daf7e3912..854fd46ab 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -26,9 +26,12 @@ #include #include +#include +#include #include #include #include +#include #include @@ -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; } diff --git a/channels/rdpei/client/rdpei_main.h b/channels/rdpei/client/rdpei_main.h index 46b549469..c0d0d2d67 100644 --- a/channels/rdpei/client/rdpei_main.h +++ b/channels/rdpei/client/rdpei_main.h @@ -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; diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 458b7dfdf..a0d7e5a04 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -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); }