You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式Qt/QML应用无法接收键盘事件(Linux帧缓冲/VNC/systemd)

问题:ARM嵌入式设备Qt/QML应用无法响应VNC及USB键盘事件

我需要远程控制ARM嵌入式设备上的Qt/QML应用,计划用VNC实现,但按键无响应,同时设备本地USB键盘也无法工作。

背景信息

  • 应用平时通过GPIO硬键控制,自定义代码将硬键输入转为Qt事件发送:
QCoreApplication::postEvent(..., new QKeyEvent(QEvent::KeyPress, ...));
  • 尝试VNC方案:
    • 设备端启动命令:
      x11vnc -rawfb map:/dev/fb0@800x480x32 -forever -rotate -90 -dk
      
    • PC端连接命令:
      gvncviewer 192.168.1.1:0
      
    • 屏幕可正常显示,但Qt应用完全不响应VNC发送的按键。
  • Qt应用通过systemd服务启动,已尝试绑定TTY,服务配置:
[Unit]
Description=Instrument IHM
After=network.target

[Service]
StandardInput=tty-force
StandardOutput=tty
StandardError=tty
TTYPath=/dev/tty0
Restart=always
ExecStartPost=/path/to/my_application --platform linuxfb:fb=/dev/fb0:rotation=90 -plugin evdevkeyboard:/dev/input/event0
Restart=on-failure
RestartSec=2s

[Install]
WantedBy=multi-user.target
  • VNC服务器日志已捕获到键盘事件(示例片段):
05/03/2024 09:17:30 # keyboard(down, 0xff54 "Down") uip=0  14.6279
05/03/2024 09:17:31 # keyboard(up, 0xff54 "Down") uip=0  14.7875
05/03/2024 09:17:32 # keyboard(down, 0xff52 "Up") uip=0  15.7994
05/03/2024 09:17:32 # keyboard(up, 0xff52 "Up") uip=0  15.8880

解决方案

1. 修复systemd服务启动命令错误

你的systemd配置误用了ExecStartPost,该指令是主服务启动后执行的命令,而非启动应用的指令。需替换为ExecStart:

[Service]
# 替换ExecStartPost为ExecStart
ExecStart=/path/to/my_application --platform linuxfb:fb=/dev/fb0:rotation=90 -plugin evdevkeyboard:/dev/input/event0

ExecStartPost会让应用脱离systemd的TTY绑定上下文,导致无法正确接收输入事件。

2. 确认evdevkeyboard插件的设备路径

  • 查看设备输入节点列表:
    ls /dev/input/
    
  • 用evtest验证目标节点是否为键盘设备:
    evtest /dev/input/event0
    
    若event0不是键盘设备,替换为正确的节点(如event1)。

3. 调整VNC服务器的事件注入方式

当前x11vnc -rawfb模式仅捕获帧缓冲,无法直接向LinuxFB平台的Qt应用注入事件,可尝试两种方案:

方案A:使用fbvncserver(专为LinuxFB设计)

安装后启动:

fbvncserver -f /dev/fb0 -w 800 -h 480 -d 32 -r -90

该VNC服务器直接操作帧缓冲,同时支持向evdev设备注入事件,Qt的evdevkeyboard插件可直接捕获。

方案B:启用x11vnc的uinput模拟

通过uinput模块模拟输入设备,启动命令添加-uinput参数:

x11vnc -rawfb map:/dev/fb0@800x480x32 -forever -rotate -90 -dk -uinput

需确保内核已加载uinput模块:

modprobe uinput

4. 验证Qt应用的事件接收逻辑

  • 在应用中添加日志,打印所有键盘事件:
    bool MyWindow::event(QEvent *event) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            qDebug() << "Received key press:" << keyEvent->key();
        }
        return QWidget::event(event);
    }
    
  • 确保窗口可获取焦点:
    Window {
        focusPolicy: Qt.StrongFocus
        // ...
    }
    

5. 修复权限问题

  • 临时赋予设备节点读写权限:
    chmod 666 /dev/input/event0 /dev/fb0
    
  • 永久解决:将应用运行用户加入input和video组:
    usermod -aG input,video your_username
    

内容的提问来源于stack exchange,提问作者Jean-Loup Sabatier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:24:53