FreeRDP
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 
25 BOOL 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 
47 static 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 
58 static 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 
76 static 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 
152 HANDLE 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 
167 BOOL 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 
191 ANDROID_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 
204 static void android_event_key_free(ANDROID_EVENT_KEY* event)
205 {
206  free(event);
207 }
208 
209 ANDROID_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 
223 static void android_event_unicodekey_free(ANDROID_EVENT_KEY* event)
224 {
225  free(event);
226 }
227 
228 ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y)
229 {
230  ANDROID_EVENT_CURSOR* event;
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 
243 static void android_event_cursor_free(ANDROID_EVENT_CURSOR* event)
244 {
245  free(event);
246 }
247 
248 ANDROID_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 
260 static void android_event_disconnect_free(ANDROID_EVENT* event)
261 {
262  free(event);
263 }
264 
265 ANDROID_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 
292 static void android_event_clipboard_free(ANDROID_EVENT_CLIPBOARD* event)
293 {
294  if (event)
295  {
296  free(event->data);
297  free(event);
298  }
299 }
300 
301 BOOL 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 
337 void 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 
368 void 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 }