xfreerdp-client: start trying to send multitouch events

This commit is contained in:
Marc-André Moreau
2013-05-13 19:17:25 -04:00
parent d96249e19f
commit b385e61bc0
10 changed files with 252 additions and 77 deletions

View File

@@ -33,6 +33,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-common freerdp-utils)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-sysinfo)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@@ -27,6 +27,7 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <freerdp/addin.h>
@@ -35,14 +36,7 @@
#include "rdpei_main.h"
struct _RDPEI_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
};
typedef struct _RDPEI_LISTENER_CALLBACK RDPEI_LISTENER_CALLBACK;
#define MAX_CONTACTS 512
struct _RDPEI_CHANNEL_CALLBACK
{
@@ -54,12 +48,28 @@ struct _RDPEI_CHANNEL_CALLBACK
};
typedef struct _RDPEI_CHANNEL_CALLBACK RDPEI_CHANNEL_CALLBACK;
struct _RDPEI_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
RDPEI_CHANNEL_CALLBACK* channel_callback;
};
typedef struct _RDPEI_LISTENER_CALLBACK RDPEI_LISTENER_CALLBACK;
struct _RDPEI_PLUGIN
{
IWTSPlugin iface;
IWTSListener* listener;
RDPEI_LISTENER_CALLBACK* listener_callback;
int version;
UINT64 currentFrameTime;
UINT64 previousFrameTime;
RDPINPUT_TOUCH_FRAME frame;
RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS];
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
@@ -164,29 +174,24 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
return 0;
}
int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback)
int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_FRAME* frame)
{
int status;
wStream* s;
UINT32 pduLength;
UINT32 encodeTime;
UINT16 frameCount;
RDPINPUT_TOUCH_FRAME frame;
RDPINPUT_CONTACT_DATA contact;
encodeTime = 123;
encodeTime = 0;
frameCount = 1;
frame.contactCount = 1;
frame.contacts = &contact;
s = Stream_New(NULL, 512);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
rdpei_write_4byte_unsigned(s, encodeTime);
rdpei_write_2byte_unsigned(s, frameCount);
rdpei_write_touch_frame(s, &frame);
rdpei_write_touch_frame(s, frame);
Stream_SealLength(s);
pduLength = Stream_Length(s);
@@ -298,6 +303,7 @@ static int rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
listener_callback->channel_callback = callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
@@ -343,7 +349,53 @@ static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
int rdpei_get_version(RdpeiClientContext* context)
{
//RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
return rdpei->version;
}
int rdpei_begin_frame(RdpeiClientContext* context)
{
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
rdpei->frame.contactCount = 0;
rdpei->frame.frameOffset = 0;
return 1;
}
int rdpei_end_frame(RdpeiClientContext* context)
{
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback;
if (!rdpei->previousFrameTime && !rdpei->currentFrameTime)
{
rdpei->currentFrameTime = (UINT64) GetTickCount64();
rdpei->frame.frameOffset = 0;
}
else
{
rdpei->currentFrameTime = (UINT64) GetTickCount64();
rdpei->frame.frameOffset = rdpei->currentFrameTime - rdpei->previousFrameTime;
}
rdpei_send_touch_event_pdu(callback, &rdpei->frame);
rdpei->previousFrameTime = rdpei->currentFrameTime;
rdpei->frame.contactCount = 0;
return 1;
}
int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact)
{
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++;
}
return 1;
}
@@ -369,10 +421,18 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->iface.Disconnected = NULL;
rdpei->iface.Terminated = rdpei_plugin_terminated;
rdpei->version = 1;
rdpei->currentFrameTime = 0;
rdpei->previousFrameTime = 0;
rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*) rdpei->contacts;
context = (RdpeiClientContext*) malloc(sizeof(RdpeiClientContext));
context->handle = (void*) rdpei;
context->GetVersion = rdpei_get_version;
context->BeginFrame = rdpei_begin_frame;
context->EndFrame = rdpei_end_frame;
context->AddContact = rdpei_add_contact;
rdpei->iface.pInterface = (void*) context;

View File

@@ -33,41 +33,6 @@
#define RDPINPUT_HEADER_LENGTH 6
#define CONTACT_DATA_CONTACTRECT_PRESENT 0x0001
#define CONTACT_DATA_ORIENTATION_PRESENT 0x0002
#define CONTACT_DATA_PRESSURE_PRESENT 0x0004
#define CONTACT_FLAG_DOWN 0x0001
#define CONTACT_FLAG_UPDATE 0x0002
#define CONTACT_FLAG_UP 0x0004
#define CONTACT_FLAG_INRANGE 0x0008
#define CONTACT_FLAG_INCONTACT 0x0010
#define CONTACT_FLAG_CANCELED 0x0020
struct _RDPINPUT_CONTACT_DATA
{
UINT32 contactId;
UINT32 fieldsPresent;
INT32 x;
INT32 y;
UINT32 contactFlags;
INT32 contactRectLeft;
INT32 contactRectTop;
INT32 contactRectRight;
INT32 contactRectBottom;
UINT32 orientation;
UINT32 pressure;
};
typedef struct _RDPINPUT_CONTACT_DATA RDPINPUT_CONTACT_DATA;
struct _RDPINPUT_TOUCH_FRAME
{
UINT32 contactCount;
UINT64 frameOffset;
RDPINPUT_CONTACT_DATA* contacts;
};
typedef struct _RDPINPUT_TOUCH_FRAME RDPINPUT_TOUCH_FRAME;
/* Protocol Version */
#define RDPINPUT_PROTOCOL_V1 0x00010000

View File

@@ -32,6 +32,8 @@ set(${MODULE_PREFIX}_SRCS
xf_event.h
xf_input.c
xf_input.h
xf_channels.c
xf_channels.h
xf_cliprdr.c
xf_cliprdr.h
xf_monitor.c

46
client/X11/xf_channels.c Normal file
View File

@@ -0,0 +1,46 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Client Channels
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf_channels.h"
#include "xf_interface.h"
#include "xfreerdp.h"
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface)
{
xfInfo* xfi = ((xfContext*) instance->context)->xfi;
printf("OnChannelConnected: %s\n", name);
if (strcmp(name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
xfi->rdpei = (RdpeiClientContext*) pInterface;
}
return 0;
}
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface)
{
return 0;
}

30
client/X11/xf_channels.h Normal file
View File

@@ -0,0 +1,30 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Client Channels
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __XF_CHANNELS_H
#define __XF_CHANNELS_H
#include <freerdp/freerdp.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);
#endif

View File

@@ -94,13 +94,13 @@ int xf_input_init(xfInfo* xfi, Window window)
for (j = 0; j < dev->num_classes; j++)
{
XIAnyClassInfo* class = dev->classes[j];
//XITouchClassInfo* t = (XITouchClassInfo*) class;
XITouchClassInfo* t = (XITouchClassInfo*) class;
if (class->type != XITouchClass)
continue;
//printf("%s %s touch device, supporting %d touches.\n",
// dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", t->num_touches);
printf("%s %s touch device, supporting %d touches.\n",
dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", t->num_touches);
}
}
@@ -257,7 +257,7 @@ void xf_input_touch_end(xfInfo* xfi, XIDeviceEvent* event)
//contacts[i].pos_y = (int)event->event_y;
active_contacts--;
break;
break;printf("TouchBegin\n");
}
}
}
@@ -301,18 +301,50 @@ int xf_input_handle_event_local(xfInfo* xfi, XEvent* event)
return 0;
}
int xf_input_touch_begin_remote(xfInfo* xfi, XIDeviceEvent* event)
char* xf_input_touch_state_string(DWORD flags)
{
return 0;
if (flags & CONTACT_FLAG_DOWN)
return "TouchBegin";
else if (flags & CONTACT_FLAG_UPDATE)
return "TouchUpdate";
else if (flags & CONTACT_FLAG_UP)
return "TouchEnd";
else
return "TouchUnknown";
}
int xf_input_touch_update_remote(xfInfo* xfi, XIDeviceEvent* event)
int xf_input_touch_remote(xfInfo* xfi, XIDeviceEvent* event, DWORD flags)
{
return 0;
}
int x, y;
int touchId;
RDPINPUT_CONTACT_DATA contact;
RdpeiClientContext* rdpei = xfi->rdpei;
if (!rdpei)
return 0;
touchId = event->detail;
x = (int) event->event_x;
y = (int) event->event_y;
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
if ((x < 0) || (y < 0))
return 0;
printf("%s: id: %d x: %d y: %d\n",
xf_input_touch_state_string(flags),
touchId, x, y);
contact.contactId = touchId % 0xFF;
contact.fieldsPresent = 0;
contact.x = x;
contact.y = y;
contact.contactFlags = flags;
rdpei->BeginFrame(rdpei);
rdpei->AddContact(rdpei, &contact);
rdpei->EndFrame(rdpei);
int xf_input_touch_end_remote(xfInfo* xfi, XIDeviceEvent* event)
{
return 0;
}
@@ -327,15 +359,15 @@ int xf_input_handle_event_remote(xfInfo* xfi, XEvent* event)
switch (cookie->evtype)
{
case XI_TouchBegin:
xf_input_touch_begin_remote(xfi, cookie->data);
xf_input_touch_remote(xfi, cookie->data, CONTACT_FLAG_DOWN);
break;
case XI_TouchUpdate:
xf_input_touch_update_remote(xfi, cookie->data);
xf_input_touch_remote(xfi, cookie->data, CONTACT_FLAG_UPDATE);
break;
case XI_TouchEnd:
xf_input_touch_end_remote(xfi, cookie->data);
xf_input_touch_remote(xfi, cookie->data, CONTACT_FLAG_UP);
break;
default:

View File

@@ -83,6 +83,7 @@
#include "xf_monitor.h"
#include "xf_graphics.h"
#include "xf_keyboard.h"
#include "xf_channels.h"
#include "xfreerdp.h"
@@ -653,17 +654,6 @@ int _xf_error_handler(Display* d, XErrorEvent* ev)
return xf_error_handler(d, ev);
}
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface)
{
//printf("OnChannelConnected: %s\n", name);
return 0;
}
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface)
{
return 0;
}
/**
* Callback given to freerdp_connect() to process the pre-connect operations.
* It will fill the rdp_freerdp structure (instance) with the appropriate options to use for the connection.

View File

@@ -22,6 +22,7 @@
#include "xf_window.h"
#include "xf_monitor.h"
#include "xf_channels.h"
struct xf_WorkArea
{
@@ -162,6 +163,9 @@ struct xf_info
Atom WM_STATE;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
/* Channels */
RdpeiClientContext* rdpei;
};
void xf_create_window(xfInfo* xfi);

View File

@@ -20,6 +20,41 @@
#ifndef FREERDP_CHANNEL_CLIENT_RDPEI_H
#define FREERDP_CHANNEL_CLIENT_RDPEI_H
#define CONTACT_DATA_CONTACTRECT_PRESENT 0x0001
#define CONTACT_DATA_ORIENTATION_PRESENT 0x0002
#define CONTACT_DATA_PRESSURE_PRESENT 0x0004
#define CONTACT_FLAG_DOWN 0x0001
#define CONTACT_FLAG_UPDATE 0x0002
#define CONTACT_FLAG_UP 0x0004
#define CONTACT_FLAG_INRANGE 0x0008
#define CONTACT_FLAG_INCONTACT 0x0010
#define CONTACT_FLAG_CANCELED 0x0020
struct _RDPINPUT_CONTACT_DATA
{
UINT32 contactId;
UINT32 fieldsPresent;
INT32 x;
INT32 y;
UINT32 contactFlags;
INT32 contactRectLeft;
INT32 contactRectTop;
INT32 contactRectRight;
INT32 contactRectBottom;
UINT32 orientation;
UINT32 pressure;
};
typedef struct _RDPINPUT_CONTACT_DATA RDPINPUT_CONTACT_DATA;
struct _RDPINPUT_TOUCH_FRAME
{
UINT32 contactCount;
UINT64 frameOffset;
RDPINPUT_CONTACT_DATA* contacts;
};
typedef struct _RDPINPUT_TOUCH_FRAME RDPINPUT_TOUCH_FRAME;
/**
* Client Interface
*/
@@ -29,6 +64,9 @@
typedef struct _rdpei_client_context RdpeiClientContext;
typedef int (*pcRdpeiGetVersion)(RdpeiClientContext* context);
typedef int (*pcRdpeiBeginFrame)(RdpeiClientContext* context);
typedef int (*pcRdpeiEndFrame)(RdpeiClientContext* context);
typedef int (*pcRdpeiAddContact)(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact);
struct _rdpei_client_context
{
@@ -36,6 +74,9 @@ struct _rdpei_client_context
void* custom;
pcRdpeiGetVersion GetVersion;
pcRdpeiBeginFrame BeginFrame;
pcRdpeiEndFrame EndFrame;
pcRdpeiAddContact AddContact;
};
#endif /* FREERDP_CHANNEL_CLIENT_RDPEI_H */