FreeRDP
Loading...
Searching...
No Matches
android_event.c
1
13#include <freerdp/config.h>
14
15#include <winpr/crt.h>
16
17#include <freerdp/freerdp.h>
18#include <freerdp/log.h>
19
20#define TAG CLIENT_TAG("android")
21
22#include "android_freerdp.h"
23#include "android_cliprdr.h"
24
25BOOL android_push_event(freerdp* inst, ANDROID_EVENT* event)
26{
27 androidContext* aCtx = (androidContext*)inst->context;
28
29 if (aCtx->event_queue->count >= aCtx->event_queue->size)
30 {
31 int new_size;
32 void* new_events;
33 new_size = aCtx->event_queue->size * 2;
34 new_events = realloc((void*)aCtx->event_queue->events, sizeof(ANDROID_EVENT*) * new_size);
35
36 if (!new_events)
37 return FALSE;
38
39 aCtx->event_queue->events = new_events;
40 aCtx->event_queue->size = new_size;
41 }
42
43 aCtx->event_queue->events[(aCtx->event_queue->count)++] = event;
44 return SetEvent(aCtx->event_queue->isSet);
45}
46
47static ANDROID_EVENT* android_peek_event(ANDROID_EVENT_QUEUE* queue)
48{
49 ANDROID_EVENT* event;
50
51 if (queue->count < 1)
52 return NULL;
53
54 event = queue->events[0];
55 return event;
56}
57
58static ANDROID_EVENT* android_pop_event(ANDROID_EVENT_QUEUE* queue)
59{
60 ANDROID_EVENT* event;
61
62 if (queue->count < 1)
63 return NULL;
64
65 event = queue->events[0];
66 (queue->count)--;
67
68 for (size_t i = 0; i < queue->count; i++)
69 {
70 queue->events[i] = queue->events[i + 1];
71 }
72
73 return event;
74}
75
76static BOOL android_process_event(ANDROID_EVENT_QUEUE* queue, freerdp* inst)
77{
78 rdpContext* context;
79
80 WINPR_ASSERT(queue);
81 WINPR_ASSERT(inst);
82
83 context = inst->context;
84 WINPR_ASSERT(context);
85
86 while (android_peek_event(queue))
87 {
88 BOOL rc = FALSE;
89 androidContext* afc = (androidContext*)context;
90 ANDROID_EVENT* event = android_pop_event(queue);
91
92 WINPR_ASSERT(event);
93
94 switch (event->type)
95 {
96 case EVENT_TYPE_KEY:
97 {
98 ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*)event;
99
100 rc = freerdp_input_send_keyboard_event(context->input, key_event->flags,
101 key_event->scancode);
102 }
103 break;
104
105 case EVENT_TYPE_KEY_UNICODE:
106 {
107 ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*)event;
108
109 rc = freerdp_input_send_unicode_keyboard_event(context->input, key_event->flags,
110 key_event->scancode);
111 }
112 break;
113
114 case EVENT_TYPE_CURSOR:
115 {
116 ANDROID_EVENT_CURSOR* cursor_event = (ANDROID_EVENT_CURSOR*)event;
117
118 rc = freerdp_input_send_mouse_event(context->input, cursor_event->flags,
119 cursor_event->x, cursor_event->y);
120 }
121 break;
122
123 case EVENT_TYPE_CLIPBOARD:
124 {
125 ANDROID_EVENT_CLIPBOARD* clipboard_event = (ANDROID_EVENT_CLIPBOARD*)event;
126 UINT32 formatId = ClipboardRegisterFormat(afc->clipboard, "text/plain");
127 UINT32 size = clipboard_event->data_length;
128
129 if (size)
130 ClipboardSetData(afc->clipboard, formatId, clipboard_event->data, size);
131 else
132 ClipboardEmpty(afc->clipboard);
133
134 rc = (android_cliprdr_send_client_format_list(afc->cliprdr) == CHANNEL_RC_OK);
135 }
136 break;
137
138 case EVENT_TYPE_DISCONNECT:
139 default:
140 break;
141 }
142
143 android_event_free(event);
144
145 if (!rc)
146 return FALSE;
147 }
148
149 return TRUE;
150}
151
152HANDLE android_get_handle(freerdp* inst)
153{
154 androidContext* aCtx;
155
156 if (!inst || !inst->context)
157 return NULL;
158
159 aCtx = (androidContext*)inst->context;
160
161 if (!aCtx->event_queue || !aCtx->event_queue->isSet)
162 return NULL;
163
164 return aCtx->event_queue->isSet;
165}
166
167BOOL android_check_handle(freerdp* inst)
168{
169 androidContext* aCtx;
170
171 if (!inst || !inst->context)
172 return FALSE;
173
174 aCtx = (androidContext*)inst->context;
175
176 if (!aCtx->event_queue || !aCtx->event_queue->isSet)
177 return FALSE;
178
179 if (WaitForSingleObject(aCtx->event_queue->isSet, 0) == WAIT_OBJECT_0)
180 {
181 if (!ResetEvent(aCtx->event_queue->isSet))
182 return FALSE;
183
184 if (!android_process_event(aCtx->event_queue, inst))
185 return FALSE;
186 }
187
188 return TRUE;
189}
190
191ANDROID_EVENT_KEY* android_event_key_new(int flags, UINT16 scancode)
192{
193 ANDROID_EVENT_KEY* event = (ANDROID_EVENT_KEY*)calloc(1, sizeof(ANDROID_EVENT_KEY));
194
195 if (!event)
196 return NULL;
197
198 event->type = EVENT_TYPE_KEY;
199 event->flags = flags;
200 event->scancode = scancode;
201 return event;
202}
203
204static void android_event_key_free(ANDROID_EVENT_KEY* event)
205{
206 free(event);
207}
208
209ANDROID_EVENT_KEY* android_event_unicodekey_new(UINT16 flags, UINT16 key)
210{
211 ANDROID_EVENT_KEY* event;
212 event = (ANDROID_EVENT_KEY*)calloc(1, sizeof(ANDROID_EVENT_KEY));
213
214 if (!event)
215 return NULL;
216
217 event->type = EVENT_TYPE_KEY_UNICODE;
218 event->flags = flags;
219 event->scancode = key;
220 return event;
221}
222
223static void android_event_unicodekey_free(ANDROID_EVENT_KEY* event)
224{
225 free(event);
226}
227
228ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y)
229{
231 event = (ANDROID_EVENT_CURSOR*)calloc(1, sizeof(ANDROID_EVENT_CURSOR));
232
233 if (!event)
234 return NULL;
235
236 event->type = EVENT_TYPE_CURSOR;
237 event->x = x;
238 event->y = y;
239 event->flags = flags;
240 return event;
241}
242
243static void android_event_cursor_free(ANDROID_EVENT_CURSOR* event)
244{
245 free(event);
246}
247
248ANDROID_EVENT* android_event_disconnect_new(void)
249{
250 ANDROID_EVENT* event;
251 event = (ANDROID_EVENT*)calloc(1, sizeof(ANDROID_EVENT));
252
253 if (!event)
254 return NULL;
255
256 event->type = EVENT_TYPE_DISCONNECT;
257 return event;
258}
259
260static void android_event_disconnect_free(ANDROID_EVENT* event)
261{
262 free(event);
263}
264
265ANDROID_EVENT_CLIPBOARD* android_event_clipboard_new(const void* data, size_t data_length)
266{
268 event = (ANDROID_EVENT_CLIPBOARD*)calloc(1, sizeof(ANDROID_EVENT_CLIPBOARD));
269
270 if (!event)
271 return NULL;
272
273 event->type = EVENT_TYPE_CLIPBOARD;
274
275 if (data)
276 {
277 event->data = calloc(data_length + 1, sizeof(char));
278
279 if (!event->data)
280 {
281 free(event);
282 return NULL;
283 }
284
285 memcpy(event->data, data, data_length);
286 event->data_length = data_length + 1;
287 }
288
289 return event;
290}
291
292static void android_event_clipboard_free(ANDROID_EVENT_CLIPBOARD* event)
293{
294 if (event)
295 {
296 free(event->data);
297 free(event);
298 }
299}
300
301BOOL android_event_queue_init(freerdp* inst)
302{
303 androidContext* aCtx = (androidContext*)inst->context;
304 ANDROID_EVENT_QUEUE* queue;
305 queue = (ANDROID_EVENT_QUEUE*)calloc(1, sizeof(ANDROID_EVENT_QUEUE));
306
307 if (!queue)
308 {
309 WLog_ERR(TAG, "android_event_queue_init: memory allocation failed");
310 return FALSE;
311 }
312
313 queue->size = 16;
314 queue->count = 0;
315 queue->isSet = CreateEventA(NULL, TRUE, FALSE, NULL);
316
317 if (!queue->isSet)
318 {
319 free(queue);
320 return FALSE;
321 }
322
323 queue->events = (ANDROID_EVENT**)calloc(queue->size, sizeof(ANDROID_EVENT*));
324
325 if (!queue->events)
326 {
327 WLog_ERR(TAG, "android_event_queue_init: memory allocation failed");
328 (void)CloseHandle(queue->isSet);
329 free(queue);
330 return FALSE;
331 }
332
333 aCtx->event_queue = queue;
334 return TRUE;
335}
336
337void android_event_queue_uninit(freerdp* inst)
338{
339 androidContext* aCtx;
340 ANDROID_EVENT_QUEUE* queue;
341
342 if (!inst || !inst->context)
343 return;
344
345 aCtx = (androidContext*)inst->context;
346 queue = aCtx->event_queue;
347
348 if (queue)
349 {
350 if (queue->isSet)
351 {
352 (void)CloseHandle(queue->isSet);
353 queue->isSet = NULL;
354 }
355
356 if (queue->events)
357 {
358 free(queue->events);
359 queue->events = NULL;
360 queue->size = 0;
361 queue->count = 0;
362 }
363
364 free(queue);
365 }
366}
367
368void android_event_free(ANDROID_EVENT* event)
369{
370 if (!event)
371 return;
372
373 switch (event->type)
374 {
375 case EVENT_TYPE_KEY:
376 android_event_key_free((ANDROID_EVENT_KEY*)event);
377 break;
378
379 case EVENT_TYPE_KEY_UNICODE:
380 android_event_unicodekey_free((ANDROID_EVENT_KEY*)event);
381 break;
382
383 case EVENT_TYPE_CURSOR:
384 android_event_cursor_free((ANDROID_EVENT_CURSOR*)event);
385 break;
386
387 case EVENT_TYPE_DISCONNECT:
388 android_event_disconnect_free((ANDROID_EVENT*)event);
389 break;
390
391 case EVENT_TYPE_CLIPBOARD:
392 android_event_clipboard_free((ANDROID_EVENT_CLIPBOARD*)event);
393 break;
394
395 default:
396 break;
397 }
398}