问题背景
使用android端 app todesk对Windows端进行远控操作过程中,受控端出现部分区域鼠标光标无法抵达,影响了远程桌面操作。
问题初步定位判断
在操作过程中,OpenFDE端的todesk控制端鼠标光标已经处在屏幕边缘了,而Windows受控端鼠标光标没有到达屏幕边缘,控制端鼠标再向屏幕外方向移动时,Windows端鼠标光标不再向对应的方向移动。此时OpenFDE可能没有产生正确的鼠标移动偏移量给到todesk,todesk控制端向受控端发送的鼠标移动事件的相对坐标偏移量可能为0。todesk远控过程中,鼠标移动事件的传递大致流程,如下图。
对于上面的初步判断,开始对OpenFDE的鼠标事件传递流程中的关键节点进行调试分析验证。
hardware/waydroid/hwcomposer/wayland-hwc.cpp:
static void pointer_handle_motion(void *data, struct wl_pointer *, uint32_t, wl_fixed_t sx, wl_fixed_t sy)此函数是鼠标移动时触发接收鼠标移动事件的回调函数,对其添加日志打印显示如下:
鼠标向上移动到屏幕上方边缘
鼠标向下移动到屏幕下方边缘
鼠标向左移动到屏幕左侧边缘
鼠标向右移动到屏幕右侧边缘
pointer_handle_motion接收的是鼠标移动后的绝对坐标x,y值,再利用保存的上一次的绝对坐标值进行差值计算得到鼠标的相对移动坐标偏移值。
再往屏幕外移动鼠标时,x,y的相对移动量为0。而todesk受控端的鼠标移动计算依赖了这个相对移动量。进而导致受控端鼠标出现结界问题。
问题详细分析与解决
以weston作为OpenFDE的窗口管理器为例(mutter情况类似),问题分为两种情形:
一、从登录界面选择weston直接启动weston运行OpenFDE。
首先通过gdb调试fde-weston进程得到如下调用栈信息:
其中关键函数handle_pointer_motion处理逻辑如下图:
直接登录启动weston方式中,鼠标移动事件直接通过libinput函数库从鼠标驱动程序获取,没有经过Xorg。在weston的libinput-device.c的handle_pointer_motion函数中,通过
libinput_event_pointer_get_dx和libinput_event_pointer_get_dy从libinput获取dx和dy相对坐标值(封装在libinput_event_pointer结构体),
接口在/usr/lib/aarch64-linux-gnu/libinput.so.10库(所在deb包名libinput10)中定义。libinput 通过Linux提供的抽象层evdev与鼠标硬件驱动程序交互。始终能收到鼠标移动的偏移值。
后面在wayland-hwc中发现有一个handle_relative_motion的函数未使用到,在此函数中可直接获取到相对移动量dx、dy和取消加速的相对移动量dx_unaccel,dy_unaccel。
分析Wayland扩展协议文件relative-pointer-unstable-v1-client-protocol和使用示例文件relative-pointer-unstable-v1.c。
修改wayland-hwc.cpp文件,补充定义zwp_relative_pointer_v1_listener监听(将协议中的relative_motion函数指针指到handle_relative_motion),
并在seat_handle_capabilities函数中调用zwp_relative_pointer_v1_add_listener添加此监听。
添加监听回调后hwc端的调用栈信息如下图所示:
修改后,情形一从登录界面选择weston直接启动weston运行OpenFDE,测试todesk操作受控端鼠标结界无法到达屏幕边缘的问题解决。
二、从登录界面先启动麒麟UKUI,在麒麟桌面以虚拟机运行方式再启动weston运行OpenFDE。
修复完情形一后,虚拟机运行方式weston启动的FDE,todesk鼠标操作还是存在结界的问题。进而对这种情形做进一步分析,首先通过gdb调试fde-weston进程得到如下调用栈信息:
其中关键函数x11_backend_deliver_motion_event处理逻辑如下图:
麒麟桌面跑的Xorg,libinput接收的鼠标移动事件会先给到Xorg,而麒麟桌面应用启动的weston FDE窗口作为X Client端从Xorg获取鼠标移动后的x,y绝对坐标值,在x11_backend中保存了上一次的x,y值,计算前后的差值dx,dy封装成weston_pointer_motion_event事件通过管道派发给hwc。
x11在鼠标移动事件的交互处理设计上存在一些缺陷,其鼠标移动坐标偏移dx、dy值是通过移动前后的x、y的差值计算得来的。在屏幕边缘向外移动时,前后两次的绝对坐标值相同均达到最大或最小,进而导致dx,dy的值为0。
情形二的解决方案:修改weston源码x11.c文件,在x11_backend_deliver_motion_event函数中将上一次的dx、dy作为惯性差值保存到static变量中,当检测到当前差值为0且在屏幕边缘时继续发送之前保存的惯性差值,另外避免移动过于缓慢而设置了一个差值阈值,原始差值的绝对值低于3时则以3或-3作为差值发送,高于3时则按原始差值发送。修改后目前这种方式下todesk远控操作已达到基本可用的状态。