From 7ecce5acbef8a1454bb47438e9254321610e2431 Mon Sep 17 00:00:00 2001 From: Julian Albrecht Date: Wed, 25 Mar 2020 16:52:30 +0100 Subject: [PATCH] Adds touch support to wlfreerdp --- client/Wayland/wlf_input.c | 168 +++++++++++++++++++++++++++++++++++++++++++++ client/Wayland/wlf_input.h | 3 + client/Wayland/wlfreerdp.c | 18 +++++ uwac/libuwac/uwac-input.c | 16 +++-- 4 files changed, 201 insertions(+), 4 deletions(-) diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index 33352cf..5bbb0d0 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -22,10 +22,26 @@ #include #include +#include +#include #include "wlfreerdp.h" #include "wlf_input.h" +#define TAG CLIENT_TAG("wayland.input") + +#define MAX_CONTACTS 10 + +typedef struct touch_contact +{ + int id; + double pos_x; + double pos_y; + BOOL emulate_mouse; +} touchContact; + +static touchContact contacts[MAX_CONTACTS]; + BOOL wlf_handle_pointer_enter(freerdp* instance, const UwacPointerEnterLeaveEvent* ev) { uint32_t x, y; @@ -191,3 +207,155 @@ BOOL wlf_keyboard_enter(freerdp* instance, const UwacKeyboardEnterLeaveEvent* ev return freerdp_input_send_focus_in_event(input, 0) && freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, 0, 0); } + +BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev) +{ + uint32_t x, y; + int i; + int touchId; + int contactId; + + if (!instance || !ev || !instance->context) + return FALSE; + + touchId = ev->id; + + for (i = 0; i < MAX_CONTACTS; i++) + { + if (contacts[i].id == touchId) + { + contacts[i].id = 0; + x = contacts[i].pos_x; + y = contacts[i].pos_y; + break; + } + } + + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); + + if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) + return FALSE; + + RdpeiClientContext* rdpei = ((wlfContext*) instance->context)->rdpei; + + if (contacts[i].emulate_mouse == TRUE) + { + UINT16 flags = 0; + flags |= PTR_FLAGS_BUTTON1; + + if ((flags & ~PTR_FLAGS_DOWN) != 0) + return freerdp_input_send_mouse_event(instance->input, flags, x, y); + + return TRUE; + } + + if (!rdpei) + return FALSE; + + rdpei->TouchEnd(rdpei, touchId, x, y, &contactId); + + return TRUE; +} + +BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev) +{ + uint32_t x, y; + int i; + int touchId; + int contactId; + wlfContext* context; + + if (!instance || !ev || !instance->context) + return FALSE; + + x = ev->x; + y = ev->y; + touchId = ev->id; + + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); + + for (i = 0; i < MAX_CONTACTS; i++) + { + if (contacts[i].id == 0) + { + contacts[i].id = touchId; + contacts[i].pos_x = x; + contacts[i].pos_y = y; + contacts[i].emulate_mouse = FALSE; + break; + } + } + + if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) + return FALSE; + + context = (wlfContext*)instance->context; + RdpeiClientContext* rdpei = ((wlfContext*) instance->context)->rdpei; + + // Emulate mouse click if touch is not possible, like in login screen + if (!rdpei) + { + contacts[i].emulate_mouse = TRUE; + + UINT16 flags = 0; + flags |= PTR_FLAGS_DOWN; + flags |= PTR_FLAGS_BUTTON1; + + if ((flags & ~PTR_FLAGS_DOWN) != 0) + return freerdp_input_send_mouse_event(instance->input, flags, x, y); + + return FALSE; + } + + rdpei->TouchBegin(rdpei, touchId, x, y, &contactId); + + return TRUE; +} + +BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev) +{ + uint32_t x, y; + int i; + int touchId; + int contactId; + + if (!instance || !ev || !instance->context) + return FALSE; + + x = ev->x; + y = ev->y; + touchId = ev->id; + + for (i = 0; i < MAX_CONTACTS; i++) + { + if (contacts[i].id == touchId) + { + if(contacts[i].pos_x == x && contacts[i].pos_y == y) + { + return TRUE; + } + contacts[i].pos_x = x; + contacts[i].pos_y = y; + break; + } + } + + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); + + if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) + return FALSE; + + RdpeiClientContext* rdpei = ((wlfContext*) instance->context)->rdpei; + + if (contacts[i].emulate_mouse == TRUE) + { + return TRUE; + } + + if (!rdpei) + return FALSE; + + rdpei->TouchUpdate(rdpei, touchId, x, y, &contactId); + + return TRUE; +} diff --git a/client/Wayland/wlf_input.h b/client/Wayland/wlf_input.h index fb362c4..32c981a 100644 --- a/client/Wayland/wlf_input.h +++ b/client/Wayland/wlf_input.h @@ -30,6 +30,9 @@ BOOL wlf_handle_pointer_enter(freerdp* instance, const UwacPointerEnterLeaveEven BOOL wlf_handle_pointer_motion(freerdp* instance, const UwacPointerMotionEvent* ev); BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent* ev); BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev); +BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev); +BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev); +BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev); BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev); BOOL wlf_keyboard_enter(freerdp* instance, const UwacKeyboardEnterLeaveEvent* ev); diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index cabc560..9875bb9 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -352,6 +352,24 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) break; + case UWAC_EVENT_TOUCH_UP: + if(!wlf_handle_touch_up(instance, &event.touchUp)) + return FALSE; + + break; + + case UWAC_EVENT_TOUCH_DOWN: + if(!wlf_handle_touch_down(instance, &event.touchDown)) + return FALSE; + + break; + + case UWAC_EVENT_TOUCH_MOTION: + if(!wlf_handle_touch_motion(instance, &event.touchMotion)) + return FALSE; + + break; + case UWAC_EVENT_KEYBOARD_ENTER: if (instance->context->settings->GrabKeyboard) UwacSeatInhibitShortcuts(event.keyboard_enter_leave.seat, true); diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index ac9294e..408a064 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -495,8 +495,12 @@ static void touch_handle_down(void* data, struct wl_touch* wl_touch, uint32_t se tdata->seat = seat; tdata->id = id; - tdata->x = x_w; - tdata->y = y_w; + + float sx = wl_fixed_to_double(x_w); + float sy = wl_fixed_to_double(y_w); + + tdata->x = sx; + tdata->y = sy; #if 0 struct widget *widget; @@ -597,8 +601,12 @@ static void touch_handle_motion(void* data, struct wl_touch* wl_touch, uint32_t tdata->seat = seat; tdata->id = id; - tdata->x = x_w; - tdata->y = y_w; + + float sx = wl_fixed_to_double(x_w); + float sy = wl_fixed_to_double(y_w); + + tdata->x = sx; + tdata->y = sy; #if 0 struct touch_point *tp; -- 2.7.4