2
* FreeRDP: A Remote Desktop Protocol Implementation
5
* Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
11
* http://www.apache.org/licenses/LICENSE-2.0
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
25
#include <X11/extensions/XInput2.h>
36
#define MAX_CONTACTS 2
38
typedef struct touch_contact
49
touchContact contacts[MAX_CONTACTS];
52
XIDeviceEvent lastEvent;
53
double firstDist = -1.0;
59
const char* xf_input_get_class_string(int class)
61
if (class == XIKeyClass)
63
else if (class == XIButtonClass)
64
return "XIButtonClass";
65
else if (class == XIValuatorClass)
66
return "XIValuatorClass";
67
else if (class == XIScrollClass)
68
return "XIScrollClass";
69
else if (class == XITouchClass)
70
return "XITouchClass";
72
return "XIUnknownClass";
75
int xf_input_init(xfContext* xfc, Window window)
84
XIEventMask evmasks[64];
85
int opcode, event, error;
86
BYTE masks[8][XIMaskLen(XI_LASTEVENT)];
91
ZeroMemory(contacts, sizeof(touchContact) * MAX_CONTACTS);
93
if (!XQueryExtension(xfc->display, "XInputExtension", &opcode, &event, &error))
95
printf("XInput extension not available.\n");
99
xfc->XInputOpcode = opcode;
101
XIQueryVersion(xfc->display, &major, &minor);
103
if (major * 1000 + minor < 2002)
105
printf("Server does not support XI 2.2\n");
109
if (xfc->settings->MultiTouchInput)
110
xfc->use_xinput = TRUE;
112
info = XIQueryDevice(xfc->display, XIAllDevices, &ndevices);
114
for (i = 0; i < ndevices; i++)
117
XIDeviceInfo* dev = &info[i];
119
for (j = 0; j < dev->num_classes; j++)
121
XIAnyClassInfo* class = dev->classes[j];
122
XITouchClassInfo* t = (XITouchClassInfo*) class;
124
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
125
(strcmp(dev->name, "Virtual core pointer") != 0))
131
for (j = 0; j < dev->num_classes; j++)
133
XIAnyClassInfo* class = dev->classes[j];
134
XITouchClassInfo* t = (XITouchClassInfo*) class;
136
if (xfc->settings->MultiTouchInput)
138
printf("%s (%d) \"%s\" id: %d\n",
139
xf_input_get_class_string(class->type),
140
class->type, dev->name, dev->deviceid);
143
evmasks[nmasks].mask = masks[nmasks];
144
evmasks[nmasks].mask_len = sizeof(masks[0]);
145
ZeroMemory(masks[nmasks], sizeof(masks[0]));
146
evmasks[nmasks].deviceid = dev->deviceid;
148
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
149
(strcmp(dev->name, "Virtual core pointer") != 0))
151
if (xfc->settings->MultiTouchInput)
153
printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n",
154
dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent",
155
dev->deviceid, t->mode, t->num_touches);
158
XISetMask(masks[nmasks], XI_TouchBegin);
159
XISetMask(masks[nmasks], XI_TouchUpdate);
160
XISetMask(masks[nmasks], XI_TouchEnd);
166
if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer"))
168
printf("%s button device (id: %d, mode: %d)\n",
170
dev->deviceid, t->mode);
171
XISetMask(masks[nmasks], XI_ButtonPress);
172
XISetMask(masks[nmasks], XI_ButtonRelease);
173
XISetMask(masks[nmasks], XI_Motion);
181
xstatus = XISelectEvents(xfc->display, window, evmasks, nmasks);
186
BOOL xf_input_is_duplicate(XIDeviceEvent* event)
188
if ( (lastEvent.time == event->time) &&
189
(lastEvent.detail == event->detail) &&
190
(lastEvent.event_x == event->event_x) &&
191
(lastEvent.event_y == event->event_y) )
199
void xf_input_save_last_event(XIDeviceEvent* event)
201
lastEvent.time = event->time;
202
lastEvent.detail = event->detail;
203
lastEvent.event_x = event->event_x;
204
lastEvent.event_y = event->event_y;
207
void xf_input_detect_pinch(xfContext* xfc)
212
ResizeWindowEventArgs e;
214
if (active_contacts != 2)
220
/* first calculate the distance */
221
dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) +
222
pow(contacts[1].pos_y - contacts[0].last_y, 2.0));
224
/* if this is the first 2pt touch */
228
lastDist = firstDist;
234
delta = lastDist - dist;
236
/* compare the current distance to the first one */
237
zoom = (dist / firstDist);
240
//printf("d: %.2f\n", delta);
248
if (xfc->scale < 0.5)
251
XResizeWindow(xfc->display, xfc->window->handle, xfc->originalWidth * xfc->scale, xfc->originalHeight * xfc->scale);
253
EventArgsInit(&e, "xfreerdp");
254
e.width = (int) xfc->originalWidth * xfc->scale;
255
e.height = (int) xfc->originalHeight * xfc->scale;
256
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
265
if (xfc->scale > 1.5)
268
XResizeWindow(xfc->display, xfc->window->handle, xfc->originalWidth * xfc->scale, xfc->originalHeight * xfc->scale);
270
EventArgsInit(&e, "xfreerdp");
271
e.width = (int) xfc->originalWidth * xfc->scale;
272
e.height = (int) xfc->originalHeight * xfc->scale;
273
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
280
void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
284
for (i = 0; i < MAX_CONTACTS; i++)
286
if (contacts[i].id == 0)
288
contacts[i].id = event->detail;
289
contacts[i].count = 1;
290
contacts[i].pos_x = event->event_x;
291
contacts[i].pos_y = event->event_y;
299
void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
303
for (i = 0; i < MAX_CONTACTS; i++)
305
if (contacts[i].id == event->detail)
308
contacts[i].last_x = contacts[i].pos_x;
309
contacts[i].last_y = contacts[i].pos_y;
310
contacts[i].pos_x = event->event_x;
311
contacts[i].pos_y = event->event_y;
313
xf_input_detect_pinch(xfc);
320
void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
324
for (i = 0; i < MAX_CONTACTS; i++)
326
if (contacts[i].id == event->detail)
329
contacts[i].count = 0;
330
//contacts[i].pos_x = (int)event->event_x;
331
//contacts[i].pos_y = (int)event->event_y;
334
break;printf("TouchBegin\n");
339
int xf_input_handle_event_local(xfContext* xfc, XEvent* event)
341
XGenericEventCookie* cookie = &event->xcookie;
343
XGetEventData(xfc->display, cookie);
345
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
347
switch (cookie->evtype)
350
if (xf_input_is_duplicate(cookie->data) == FALSE)
351
xf_input_touch_begin(xfc, cookie->data);
352
xf_input_save_last_event(cookie->data);
356
if (xf_input_is_duplicate(cookie->data) == FALSE)
357
xf_input_touch_update(xfc, cookie->data);
358
xf_input_save_last_event(cookie->data);
362
if (xf_input_is_duplicate(cookie->data) == FALSE)
363
xf_input_touch_end(xfc, cookie->data);
364
xf_input_save_last_event(cookie->data);
368
printf("unhandled xi type= %d\n", cookie->evtype);
373
XFreeEventData(xfc->display,cookie);
378
char* xf_input_touch_state_string(DWORD flags)
380
if (flags & CONTACT_FLAG_DOWN)
382
else if (flags & CONTACT_FLAG_UPDATE)
383
return "TouchUpdate";
384
else if (flags & CONTACT_FLAG_UP)
387
return "TouchUnknown";
390
int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
395
RdpeiClientContext* rdpei = xfc->rdpei;
400
touchId = event->detail;
401
x = (int) event->event_x;
402
y = (int) event->event_y;
404
if (evtype == XI_TouchBegin)
406
//printf("TouchBegin: %d\n", touchId);
407
contactId = rdpei->TouchBegin(rdpei, touchId, x, y);
409
else if (evtype == XI_TouchUpdate)
411
//printf("TouchUpdate: %d\n", touchId);
412
contactId = rdpei->TouchUpdate(rdpei, touchId, x, y);
414
else if (evtype == XI_TouchEnd)
416
//printf("TouchEnd: %d\n", touchId);
417
contactId = rdpei->TouchEnd(rdpei, touchId, x, y);
423
int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
429
//printf("ButtonPress\n");
430
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
431
event->detail, event->event, xfc->remote_app);
434
case XI_ButtonRelease:
435
//printf("ButtonRelease\n");
436
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
437
event->detail, event->event, xfc->remote_app);
441
//printf("Motion\n");
442
xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y,
443
event->detail, event->event, xfc->remote_app);
450
int xf_input_handle_event_remote(xfContext* xfc, XEvent* event)
452
XGenericEventCookie* cookie = &event->xcookie;
454
XGetEventData(xfc->display, cookie);
456
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
458
switch (cookie->evtype)
461
xf_input_touch_remote(xfc, cookie->data, XI_TouchBegin);
465
xf_input_touch_remote(xfc, cookie->data, XI_TouchUpdate);
469
xf_input_touch_remote(xfc, cookie->data, XI_TouchEnd);
473
xf_input_event(xfc, cookie->data, cookie->evtype);
478
XFreeEventData(xfc->display,cookie);
485
int xf_input_init(xfContext* xfc, Window window)
492
void xf_process_rdpei_event(xfContext* xfc, wMessage* event)
494
switch (GetMessageType(event->id))
496
case RdpeiChannel_ServerReady:
499
case RdpeiChannel_SuspendTouch:
502
case RdpeiChannel_ResumeTouch:
507
int xf_input_handle_event(xfContext* xfc, XEvent* event)
510
if (xfc->settings->MultiTouchInput)
512
return xf_input_handle_event_remote(xfc, event);
515
if (xfc->enableScaling)
516
return xf_input_handle_event_local(xfc, event);