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