Skip to content

Commit

Permalink
Proper pointer event handling for wayland
Browse files Browse the repository at this point in the history
(cherry picked from commit 8732ff6)
  • Loading branch information
akallabeth committed Aug 28, 2023
1 parent c659973 commit 7073e7e
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 28 deletions.
128 changes: 116 additions & 12 deletions client/Wayland/wlf_input.c
Expand Up @@ -134,26 +134,44 @@ BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent*
}

BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
{
wlfContext* context;
if (!instance || !instance->context || !ev)
return FALSE;

context = (wlfContext*)instance->context;
ArrayList_Add(context->events, ev);
return TRUE;
}

BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev)
{
wlfContext* context;
if (!instance || !instance->context || !ev)
return FALSE;

context = (wlfContext*)instance->context;
ArrayList_Add(context->events, ev);
return TRUE;
}

static BOOL wlf_handle_wheel(freerdp* instance, uint32_t x, uint32_t y, uint32_t axis,
int32_t value)
{
rdpInput* input;
UINT16 flags = 0;
int32_t direction;
uint32_t x, y;
uint32_t i;
uint32_t avalue = abs(value);

if (!instance || !ev || !instance->input)
return FALSE;

x = ev->x;
y = ev->y;
input = instance->input;

if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
return FALSE;

input = instance->input;

direction = ev->value;
switch (ev->axis)
direction = value;
switch (axis)
{
case WL_POINTER_AXIS_VERTICAL_SCROLL:
flags |= PTR_FLAGS_WHEEL;
Expand All @@ -176,16 +194,102 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
* positive: 0 ... 0xFF -> slow ... fast
* negative: 0 ... 0xFF -> fast ... slow
*/
for (i = 0; i < abs(direction); i++)

while (avalue > 0)
{
uint32_t cflags = flags | 0x78;
const uint32_t cval = avalue > 0xFF ? 0xFF : avalue;
uint32_t cflags = flags | cval;
/* Convert negative values to 9bit twos complement */
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
cflags = (flags & 0xFF00) | (0x100 - (cflags & 0xFF));
cflags = (flags & 0xFF00) | (0x100 - cval);
if (!freerdp_input_send_mouse_event(input, cflags, (UINT16)x, (UINT16)y))
return FALSE;

avalue -= cval;
}
return TRUE;
}

BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev)
{
BOOL success = TRUE;
BOOL handle = FALSE;
size_t x;
wlfContext* context;
enum wl_pointer_axis_source source;

if (!instance || !ev || !instance->input || !instance->context)
return FALSE;

context = (wlfContext*)instance->context;

for (x = 0; x < ArrayList_Count(context->events); x++)
{
UwacEvent* ev = ArrayList_GetItem(context->events, x);
if (!ev)
continue;
if (ev->type == UWAC_EVENT_POINTER_SOURCE)
{
handle = TRUE;
source = ev->mouse_source.axis_source;
}
}

/* We need source events to determine how to interpret the data */
if (handle)
{
for (x = 0; x < ArrayList_Count(context->events); x++)
{
UwacEvent* ev = ArrayList_GetItem(context->events, x);
if (!ev)
continue;

switch (source)
{
/* If we have a mouse wheel, just use discrete data */
case WL_POINTER_AXIS_SOURCE_WHEEL:
#if defined(WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION)
case WL_POINTER_AXIS_SOURCE_WHEEL_TILT:
#endif
if (ev->type == UWAC_EVENT_POINTER_AXIS_DISCRETE)
{
/* Get the number of steps, multiply by default step width of 120 */
int32_t val = ev->mouse_axis.value * 0x78;
/* No wheel event received, success! */
if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y,
ev->mouse_axis.axis, val))
success = FALSE;
}
break;
/* If we have a touch pad we get actual data, scale */
case WL_POINTER_AXIS_SOURCE_FINGER:
case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
if (ev->type == UWAC_EVENT_POINTER_AXIS)
{
double dval = wl_fixed_to_double(ev->mouse_axis.value);
int32_t val = dval * 0x78 / 10.0;
if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y,
ev->mouse_axis.axis, val))
success = FALSE;
}
break;
default:
break;
}
}
}
ArrayList_Clear(context->events);
return success;
}

BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev)
{
wlfContext* context;
if (!instance || !instance->context || !ev)
return FALSE;

context = (wlfContext*)instance->context;
ArrayList_Add(context->events, ev);
return TRUE;
}

Expand Down
3 changes: 3 additions & 0 deletions client/Wayland/wlf_input.h
Expand Up @@ -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_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev);
BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev);
BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* 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);
Expand Down
64 changes: 48 additions & 16 deletions client/Wayland/wlfreerdp.c
Expand Up @@ -362,12 +362,22 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;

case UWAC_EVENT_POINTER_AXIS:
if (!wlf_handle_pointer_axis(instance, &event.mouse_axis))
return FALSE;
break;

case UWAC_EVENT_POINTER_AXIS_DISCRETE:
if (!wlf_handle_pointer_axis(instance, &event.mouse_axis))
if (!wlf_handle_pointer_axis_discrete(instance, &event.mouse_axis))
return FALSE;
break;

case UWAC_EVENT_POINTER_FRAME:
if (!wlf_handle_pointer_frame(instance, &event.mouse_frame))
return FALSE;
break;
case UWAC_EVENT_POINTER_SOURCE:
if (!wlf_handle_pointer_source(instance, &event.mouse_source))
return FALSE;
break;

case UWAC_EVENT_KEY:
Expand Down Expand Up @@ -561,8 +571,37 @@ static int wlf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
return 1;
}

static void wlf_client_free(freerdp* instance, rdpContext* context)
{
wlfContext* wlf = (wlfContext*)instance->context;

if (!context)
return;

if (wlf->display)
UwacCloseDisplay(&wlf->display);

if (wlf->displayHandle)
CloseHandle(wlf->displayHandle);
ArrayList_Free(wlf->events);
DeleteCriticalSection(&wlf->critical);
}

static void* uwac_event_clone(const void* val)
{
UwacEvent* copy;
UwacEvent* ev = (UwacEvent*)val;

copy = calloc(1, sizeof(UwacEvent));
if (!copy)
return NULL;
*copy = *ev;
return copy;
}

static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
{
wObject* obj;
UwacReturnCode status;
wlfContext* wfl = (wlfContext*)context;

Expand Down Expand Up @@ -590,24 +629,17 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
if (!wfl->displayHandle)
return FALSE;

InitializeCriticalSection(&wfl->critical);

return TRUE;
}

static void wlf_client_free(freerdp* instance, rdpContext* context)
{
wlfContext* wlf = (wlfContext*)instance->context;
wfl->events = ArrayList_New(FALSE);
if (!wfl->events)
return FALSE;

if (!context)
return;
obj = ArrayList_Object(wfl->events);
obj->fnObjectNew = uwac_event_clone;
obj->fnObjectFree = free;

if (wlf->display)
UwacCloseDisplay(&wlf->display);
InitializeCriticalSection(&wfl->critical);

if (wlf->displayHandle)
CloseHandle(wlf->displayHandle);
DeleteCriticalSection(&wlf->critical);
return TRUE;
}

static int wfl_client_start(rdpContext* context)
Expand Down
1 change: 1 addition & 0 deletions client/Wayland/wlfreerdp.h
Expand Up @@ -53,6 +53,7 @@ struct wlf_context
wlfDispContext* disp;
wLog* log;
CRITICAL_SECTION critical;
wArrayList* events;
};

BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP);
Expand Down

0 comments on commit 7073e7e

Please sign in to comment.