FreeRDP
wlf_input.c
1 
21 #include <stdlib.h>
22 #include <float.h>
23 
24 #include <linux/input.h>
25 
26 #include <winpr/assert.h>
27 #include <winpr/cast.h>
28 
29 #include <freerdp/config.h>
30 #include <freerdp/locale/keyboard.h>
31 #if defined(CHANNEL_RDPEI_CLIENT)
32 #include <freerdp/client/rdpei.h>
33 #endif
34 #include <uwac/uwac.h>
35 
36 #include "wlfreerdp.h"
37 #include "wlf_input.h"
38 
39 static BOOL scale_signed_coordinates(rdpContext* context, int32_t* x, int32_t* y,
40  BOOL fromLocalToRDP)
41 {
42  BOOL rc = 0;
43  UINT32 ux = 0;
44  UINT32 uy = 0;
45  WINPR_ASSERT(context);
46  WINPR_ASSERT(x);
47  WINPR_ASSERT(y);
48  WINPR_ASSERT(*x >= 0);
49  WINPR_ASSERT(*y >= 0);
50 
51  ux = (UINT32)*x;
52  uy = (UINT32)*y;
53  rc = wlf_scale_coordinates(context, &ux, &uy, fromLocalToRDP);
54  WINPR_ASSERT(ux < INT32_MAX);
55  WINPR_ASSERT(uy < INT32_MAX);
56  *x = (int32_t)ux;
57  *y = (int32_t)uy;
58  return rc;
59 }
60 
61 BOOL wlf_handle_pointer_enter(freerdp* instance, const UwacPointerEnterLeaveEvent* ev)
62 {
63  uint32_t x = 0;
64  uint32_t y = 0;
65  rdpClientContext* cctx = NULL;
66 
67  if (!instance || !ev)
68  return FALSE;
69 
70  x = ev->x;
71  y = ev->y;
72 
73  if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
74  return FALSE;
75 
76  cctx = (rdpClientContext*)instance->context;
77  return freerdp_client_send_button_event(cctx, FALSE, PTR_FLAGS_MOVE,
78  WINPR_ASSERTING_INT_CAST(int, x),
79  WINPR_ASSERTING_INT_CAST(int, y));
80 }
81 
82 BOOL wlf_handle_pointer_motion(freerdp* instance, const UwacPointerMotionEvent* ev)
83 {
84  rdpClientContext* cctx = NULL;
85 
86  if (!instance || !ev)
87  return FALSE;
88 
89  cctx = (rdpClientContext*)instance->context;
90  WINPR_ASSERT(cctx);
91 
92  uint32_t x = ev->x;
93  uint32_t y = ev->y;
94 
95  if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
96  return FALSE;
97 
98  return freerdp_client_send_button_event(cctx, FALSE, PTR_FLAGS_MOVE,
99  WINPR_ASSERTING_INT_CAST(int32_t, x),
100  WINPR_ASSERTING_INT_CAST(int32_t, y));
101 }
102 
103 BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent* ev)
104 {
105  rdpClientContext* cctx = NULL;
106  UINT16 flags = 0;
107  UINT16 xflags = 0;
108 
109  if (!instance || !ev)
110  return FALSE;
111 
112  cctx = (rdpClientContext*)instance->context;
113  WINPR_ASSERT(cctx);
114 
115  uint32_t x = ev->x;
116  uint32_t y = ev->y;
117 
118  if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
119  return FALSE;
120 
121  if (ev->state == WL_POINTER_BUTTON_STATE_PRESSED)
122  {
123  flags |= PTR_FLAGS_DOWN;
124  xflags |= PTR_XFLAGS_DOWN;
125  }
126 
127  switch (ev->button)
128  {
129  case BTN_LEFT:
130  flags |= PTR_FLAGS_BUTTON1;
131  break;
132 
133  case BTN_RIGHT:
134  flags |= PTR_FLAGS_BUTTON2;
135  break;
136 
137  case BTN_MIDDLE:
138  flags |= PTR_FLAGS_BUTTON3;
139  break;
140 
141  case BTN_SIDE:
142  xflags |= PTR_XFLAGS_BUTTON1;
143  break;
144 
145  case BTN_EXTRA:
146  xflags |= PTR_XFLAGS_BUTTON2;
147  break;
148 
149  default:
150  return TRUE;
151  }
152 
153  const INT32 cx = WINPR_ASSERTING_INT_CAST(int32_t, x);
154  const INT32 cy = WINPR_ASSERTING_INT_CAST(int32_t, y);
155 
156  if ((flags & ~PTR_FLAGS_DOWN) != 0)
157  return freerdp_client_send_button_event(cctx, FALSE, flags, cx, cy);
158 
159  if ((xflags & ~PTR_XFLAGS_DOWN) != 0)
160  return freerdp_client_send_extended_button_event(cctx, FALSE, xflags, cx, cy);
161 
162  return FALSE;
163 }
164 
165 BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
166 {
167  wlfContext* context = NULL;
168  if (!instance || !instance->context || !ev)
169  return FALSE;
170 
171  context = (wlfContext*)instance->context;
172  return ArrayList_Append(context->events, ev);
173 }
174 
175 BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev)
176 {
177  wlfContext* context = NULL;
178  if (!instance || !instance->context || !ev)
179  return FALSE;
180 
181  context = (wlfContext*)instance->context;
182  return ArrayList_Append(context->events, ev);
183 }
184 
185 static BOOL wlf_handle_wheel(freerdp* instance, uint32_t x, uint32_t y, uint32_t axis,
186  int32_t value)
187 {
188  rdpClientContext* cctx = NULL;
189  UINT16 flags = 0;
190  int32_t direction = 0;
191  uint32_t avalue = (uint32_t)abs(value);
192 
193  WINPR_ASSERT(instance);
194 
195  cctx = (rdpClientContext*)instance->context;
196  WINPR_ASSERT(cctx);
197 
198  if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
199  return FALSE;
200 
201  direction = value;
202  switch (axis)
203  {
204  case WL_POINTER_AXIS_VERTICAL_SCROLL:
205  flags |= PTR_FLAGS_WHEEL;
206  if (direction > 0)
207  flags |= PTR_FLAGS_WHEEL_NEGATIVE;
208  break;
209 
210  case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
211  flags |= PTR_FLAGS_HWHEEL;
212  if (direction < 0)
213  flags |= PTR_FLAGS_WHEEL_NEGATIVE;
214  break;
215 
216  default:
217  return FALSE;
218  }
219 
220  /* Wheel rotation steps:
221  *
222  * positive: 0 ... 0xFF -> slow ... fast
223  * negative: 0 ... 0xFF -> fast ... slow
224  */
225 
226  while (avalue > 0)
227  {
228  const UINT16 cval = (avalue > 0xFF) ? 0xFF : (UINT16)avalue;
229  UINT16 cflags = flags | cval;
230  /* Convert negative values to 9bit twos complement */
231  if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
232  cflags = (flags & 0xFF00) | (0x100 - cval);
233  if (!freerdp_client_send_wheel_event(cctx, cflags))
234  return FALSE;
235 
236  avalue -= cval;
237  }
238  return TRUE;
239 }
240 
241 BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev)
242 {
243  BOOL success = TRUE;
244  BOOL handle = FALSE;
245  wlfContext* context = NULL;
246  enum wl_pointer_axis_source source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
247 
248  if (!instance || !ev || !instance->context)
249  return FALSE;
250 
251  context = (wlfContext*)instance->context;
252 
253  for (size_t x = 0; x < ArrayList_Count(context->events); x++)
254  {
255  UwacEvent* cev = ArrayList_GetItem(context->events, x);
256  if (!cev)
257  continue;
258  if (cev->type == UWAC_EVENT_POINTER_SOURCE)
259  {
260  handle = TRUE;
261  source = cev->mouse_source.axis_source;
262  }
263  }
264 
265  /* We need source events to determine how to interpret the data */
266  if (handle)
267  {
268  for (size_t x = 0; x < ArrayList_Count(context->events); x++)
269  {
270  UwacEvent* cev = ArrayList_GetItem(context->events, x);
271  if (!cev)
272  continue;
273 
274  switch (source)
275  {
276  /* If we have a mouse wheel, just use discrete data */
277  case WL_POINTER_AXIS_SOURCE_WHEEL:
278 #if defined(WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION)
279  case WL_POINTER_AXIS_SOURCE_WHEEL_TILT:
280 #endif
281  if (cev->type == UWAC_EVENT_POINTER_AXIS_DISCRETE)
282  {
283  /* Get the number of steps, multiply by default step width of 120 */
284  int32_t val = cev->mouse_axis.value * 0x78;
285  /* No wheel event received, success! */
286  if (!wlf_handle_wheel(instance, cev->mouse_axis.x, cev->mouse_axis.y,
287  cev->mouse_axis.axis, val))
288  success = FALSE;
289  }
290  break;
291  /* If we have a touch pad we get actual data, scale */
292  case WL_POINTER_AXIS_SOURCE_FINGER:
293  case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
294  if (cev->type == UWAC_EVENT_POINTER_AXIS)
295  {
296  double dval = wl_fixed_to_double(cev->mouse_axis.value);
297  int32_t val = (int32_t)(dval * 0x78 / 10.0);
298  if (!wlf_handle_wheel(instance, cev->mouse_axis.x, cev->mouse_axis.y,
299  cev->mouse_axis.axis, val))
300  success = FALSE;
301  }
302  break;
303  default:
304  break;
305  }
306  }
307  }
308  ArrayList_Clear(context->events);
309  return success;
310 }
311 
312 BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev)
313 {
314  wlfContext* context = NULL;
315  if (!instance || !instance->context || !ev)
316  return FALSE;
317 
318  context = (wlfContext*)instance->context;
319  return ArrayList_Append(context->events, ev);
320 }
321 
322 BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev)
323 {
324  if (!instance || !ev)
325  return FALSE;
326 
327  WINPR_ASSERT(instance->context);
328  wlfContext* ctx = (wlfContext*)instance->context;
329  if (freerdp_settings_get_bool(instance->context->settings, FreeRDP_GrabKeyboard) &&
330  ev->raw_key == KEY_RIGHTCTRL)
331  wlf_handle_ungrab_key(instance, ev);
332 
333  rdpInput* input = instance->context->input;
334 
335  const DWORD vc = GetVirtualKeyCodeFromKeycode(ev->raw_key, WINPR_KEYCODE_TYPE_EVDEV);
336  const DWORD sc = GetVirtualScanCodeFromVirtualKeyCode(vc, WINPR_KBD_TYPE_IBM_ENHANCED);
337  const DWORD rdp_scancode = freerdp_keyboard_remap_key(ctx->remap_table, sc);
338 
339  if (rdp_scancode == RDP_SCANCODE_UNKNOWN)
340  return TRUE;
341 
342  return freerdp_input_send_keyboard_event_ex(input, ev->pressed, ev->repeated, rdp_scancode);
343 }
344 
345 BOOL wlf_handle_ungrab_key(freerdp* instance, const UwacKeyEvent* ev)
346 {
347  wlfContext* context = NULL;
348  if (!instance || !instance->context || !ev)
349  return FALSE;
350 
351  context = (wlfContext*)instance->context;
352 
353  return UwacSeatInhibitShortcuts(context->seat, false) == UWAC_SUCCESS;
354 }
355 
356 BOOL wlf_keyboard_enter(freerdp* instance, const UwacKeyboardEnterLeaveEvent* ev)
357 {
358  if (!instance || !ev)
359  return FALSE;
360 
361  ((wlfContext*)instance->context)->focusing = TRUE;
362  return TRUE;
363 }
364 
365 BOOL wlf_keyboard_modifiers(freerdp* instance, const UwacKeyboardModifiersEvent* ev)
366 {
367  rdpInput* input = NULL;
368  UINT16 syncFlags = 0;
369  wlfContext* wlf = NULL;
370 
371  if (!instance || !ev)
372  return FALSE;
373 
374  wlf = (wlfContext*)instance->context;
375  WINPR_ASSERT(wlf);
376 
377  input = instance->context->input;
378  WINPR_ASSERT(input);
379 
380  syncFlags = 0;
381 
382  if (ev->modifiers & UWAC_MOD_CAPS_MASK)
383  syncFlags |= KBD_SYNC_CAPS_LOCK;
384  if (ev->modifiers & UWAC_MOD_NUM_MASK)
385  syncFlags |= KBD_SYNC_NUM_LOCK;
386 
387  if (!wlf->focusing)
388  return TRUE;
389 
390  ((wlfContext*)instance->context)->focusing = FALSE;
391 
392  return freerdp_input_send_focus_in_event(input, syncFlags) &&
393  freerdp_client_send_button_event(&wlf->common, FALSE, PTR_FLAGS_MOVE, 0, 0);
394 }
395 
396 BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev)
397 {
398  int32_t x = 0;
399  int32_t y = 0;
400 
401  WINPR_ASSERT(instance);
402  WINPR_ASSERT(ev);
403 
404  wlfContext* wlf = (wlfContext*)instance->context;
405  WINPR_ASSERT(wlf);
406 
407  x = ev->x;
408  y = ev->y;
409 
410  if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
411  return FALSE;
412 
413  return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_UP, ev->id, 0, x, y);
414 }
415 
416 BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev)
417 {
418  int32_t x = 0;
419  int32_t y = 0;
420 
421  WINPR_ASSERT(instance);
422  WINPR_ASSERT(ev);
423 
424  wlfContext* wlf = (wlfContext*)instance->context;
425  WINPR_ASSERT(wlf);
426 
427  x = ev->x;
428  y = ev->y;
429 
430  if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
431  return FALSE;
432 
433  return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_DOWN, ev->id, 0, x, y);
434 }
435 
436 BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev)
437 {
438  int32_t x = 0;
439  int32_t y = 0;
440 
441  WINPR_ASSERT(instance);
442  WINPR_ASSERT(ev);
443 
444  wlfContext* wlf = (wlfContext*)instance->context;
445  WINPR_ASSERT(wlf);
446 
447  x = ev->x;
448  y = ev->y;
449 
450  if (!scale_signed_coordinates(instance->context, &x, &y, TRUE))
451  return FALSE;
452 
453  return freerdp_client_handle_touch(&wlf->common, FREERDP_TOUCH_MOTION, 0,
454  WINPR_ASSERTING_INT_CAST(uint32_t, ev->id), x, y);
455 }
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.