相对于没有视窗系统,鼠标、键盘、触摸板输入直接从evdev读取或者使用第三方的库实现比如 libinput、tslib。这需要/dev/input/event*可以被用户读取。Eglfs 和 Linuxfb 内部有所有的输入处理。

一、使用libinput

Libinput 是一个用于处理输入设备的库。相对于 Qt 直接读取 evdev,它提供了另一种实现方式。为了使用 libinput,配置编译 Qt 时需要准备 libudev 和 libinput 开发文件。如果使用键盘支持,xkbcommon 也是必需的。Eglfs 和 linuxfb 不需要其它额外的配置由于它们默认使用 libinput。如果没有 libinput 支持或者 QT_QPA_EGLFS_NO_LIBINPUT 设置了。Qt 将会使用它自己的 evdevhandlers 处理。

二、Eglfs和linuxfb不使用libinput

进行设置不使用 libinput:

  • QT_QPA_EGLFS_DISABLE_INPUT:EGLFS禁用输入,即不使用libinput
  • QT_QPA_FB_DISABLE_INPUT:LinuxFB禁用输入,即不使用libinput

另外还有一些可能要用到的相关环境变量:QT_QPA_EVDEV_MOUSE_PARAMETERS, QT_QPA_EVDEV_KEYBOARD_PARAMETERS 以及 QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS。

三、鼠标输入

鼠标光标默认会一直显示,除非设置QT_QPA_EGLFS_HIDECURSOR (for eglfs) 或者QT_QPA_FB_HIDECURSOR (for linuxfb),Qt 的基于 libudev 的设备会查看报告,报告中至少有一个鼠标可用。如果不使用 libudev,鼠标箭头会一直显示除非通过修改环境变量禁止显示。

只有使用 libudev 时才支持热插拔,它允许在应用运行的时候插拔鼠标。

四、键盘输入

Evdev 键盘处理支持以下额外参数:

  • /dev/input/... – 指定输入设备名称。如果未指定,Qt 通过 libudev 查找一个合适的设备,或者遍历所有的设备结点查找一个合适的设备
  • grab – 允许抢占输入设备
  • keymap – 指定键盘映射文件
  • enable-compose - Enables compositing
  • repeat-delay – 设置一个用户定义的按键重复延时
  • repeat-rate - 设置一个用户定义的按键重复率.

嵌入式 linux 系统的终端处理中,按键行为是被谁处理是未知的,因为输入事件既可以被 Qt 应用处理也可以被终端处理。为了解决这个问题,可以设置以下选项:

  • 在应用启动的时候设置 tty 键盘的模式 K_OFF 来禁用终端键盘处理,这将阻止键盘事件进入终端。有些情况下,标准键盘行为需要被重新载入,这里把QT_QPA_ENABLE_TERMINAL_KEYBOARD设置为1注意:这仅仅从远程终端(ssh)启动一个应用时有用,终端键盘输入保持可用。

  • 一个可选择的实现方式是使用 udev 键盘处理的 grab 参数,QT_QPA_EVDEV_KEYBOARD_PARAMETERS的参数 grab=1。这将导致抢占一次输入设备,如果抢占成功,系统中的其它组件就不会收到键盘事件。这种方式更适合于从远程启动的应用,因为不需要获取 tty 设备。

  • 如果内建的键盘映射不能满足要求,可以使用 eglfs 的loadKeymap()函数或者使用 keymap 参数来加载一个键盘映射文件。LoadKeyMap()允许在程序运行时改变键盘映射。注意,这需要使用 eglfs 内部的键盘处理,如果键盘处理是通过-plugin命令行参数的方式加载的不可以使用loadkeymap()

  • 生成一个自定义键盘映射,可以使用 kmap2qmap 工具。这个工具在 qttools 模块里。源文件必须是标准 Linux kmap 格式,这种格式可以被内核的 loadkeys 命令理解。

注意:特殊系统的键盘组合现在不被支持会被忽略比如(Ctrl+Alt+Fx) (Ctrl+Alt+Backspace)

五、触摸

对于一些电阻单点触摸屏,需要退回使用 tslib。可以通过设置环境变量QT_QPA_EGLFS_TSLIB or QT_QPA_FB_TSLIB1来启动 tslib 支持。设置 TSLIB_TSDEVICE 或者通过命令行传设备名称参数来改变设备。

注意tslib 输入处理产生鼠标事件并仅支持单点触摸,与之相对的,evdevtouch 产生真正的多点触摸 QTouchEvent 事件。

六、笔控板

Evdevtablet 插件为 Wacom 和相似的 pen-basedtables 提供基础支持,它产生 QTabletEvent 事件。QT_QPA_GENERIC_PLUGINS=evdevtablet或者命令行传递参数-plugin evdevtablet来使能 evdevtablet。该插件可以有一个设备结点参数,例如QT_QPA_GENERIC_PLUGINS=evdevtablet:/dev/event1,这时 Qt 自动查找设备就不进行自动查找了。

七、调试输入设备

通过使能qt.qpa.input日志规则,可以打印一些调试信息输出。例如:设置QT_LOGGING_RULES环境变量qt.qpa.input=true。这对于检测哪一个设备被使用或者查找设备过程中的问题解决很有帮助。

八、自定义鼠标光标图片

Eglfs 使用它自己的 32x32 的鼠标图片。如果这不能满足,用户可以指定自己的图片,方法是设置 QT_QPA_EGLFS_CURSOR 环境变量,这个环境变量是一个 JSON 文件名称。这个文件也可以通过 Qt 资源文件嵌入到应用中。

例如:一个嵌入的鼠标光标使用 8 张鼠标图片,每一行可以进行如下指定:

{
   "image": ":/cursor-atlas.png",
   "cursorsPerRow": 8,
   "hotSpots": [
        [7, 2],
        [12, 3],
        [12, 12],
        ...
   ]
 }

九、修改鼠标移动速度

Qt5 不提供官方 API 来修改鼠标移动速度,所以只能修改鼠标相关源码(/home/book/proj/xxx-sdk/buildroot/output/rockchip_xxx/build/qt5base-5.12.2/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp),重新交叉编译出libqevdevmouseplugin.so,将该动态库放到 Qt 的插件路径下,具体代码如下:

// 鼠标插件路径
#define MOUSE_PLUGIN_PATH "/usr/lib/qt/plugins/generic/libqevdevmouseplugin.so"

// 设置鼠标速度
void SetWidget::setMouseSpeed(float val)
{
    // 避免鼠标值为0的情况
    if(val<=0)
        return;

    //qDebug() << "setMouseSpeed: " << val;
    typedef void (* SET_MOUSE_SPEED)(float);
    QLibrary mouse_plugin(MOUSE_PLUGIN_PATH);
    mouse_plugin.load();
    if(mouse_plugin.isLoaded()){
        SET_MOUSE_SPEED set_speed = (SET_MOUSE_SPEED)mouse_plugin.resolve("Set_mouse_speed");
        if(set_speed){
            set_speed(val);
            mouse_plugin.unload();
        }
        else{
            printf("plugin resolve err!\n");
            mouse_plugin.unload();
        }
    }
    else{
        printf("plugin load err!\n");
    }
}

十、屏蔽 Ctrl+Shift+Backspace 快捷键

Qt 应用程序运行在 ARM 上时,如果按下 Ctrl+Shift+Backspace 快捷键,就会被强制退出应用,所以要修改源码屏蔽该快捷键(/home/book/proj/xxx-sdk/buildroot/output/rockchip_xxx/build/qt5base-5.12.2/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp)。