版本比较

密钥

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

经过编译安装后,注销重新登录。开始对Xorg进行gdb调试分析。

首先对xserver源码进行了初步的阅读分析,对GetKeyboardEvents进行断点调试。

正常按下抬起Ctrl按键时,调用栈信息打印如下:

代码块
Ctrl按键按下时的调用栈信息:
Thread 18 "InputThread" hit Breakpoint 3, GetKeyboardEvents (events=0x7f95242010, pDev=pDev@entry=0x559f0848b0, type=type@entry=2, key_code=key_code@entry=37) at ../../dix/getevents.c:1067
1067    {
(gdb) bt
#0  GetKeyboardEvents (events=0x7f95242010, pDev=pDev@entry=0x559f0848b0, type=type@entry=2, key_code=key_code@entry=37) at ../../dix/getevents.c:1067
#1  0x0000005579ac9d74 in QueueKeyboardEvents (device=device@entry=0x559f0848b0, type=type@entry=2, keycode=keycode@entry=37) at ../../dix/getevents.c:1051
#2  0x0000005579afab30 in xf86PostKeyEventM (device=device@entry=0x559f0848b0, key_code=key_code@entry=37, is_down=is_down@entry=1) at ../../../../hw/xfree86/common/xf86Xinput.c:1423
#3  0x0000005579afab9c in xf86PostKeyboardEvent (device=0x559f0848b0, key_code=37, is_down=1) at ../../../../hw/xfree86/common/xf86Xinput.c:1432
#4  0x0000007f82381e14 in  () at /usr/lib/xorg/modules/input/libinput_drv.so
#5  0x0000007f823829e4 in  () at /usr/lib/xorg/modules/input/libinput_drv.so
#6  0x0000005579bfb22c in InputReady (fd=24, xevents=1, data=0x559ee27cf0) at ../../os/inputthread.c:180
#7  0x0000005579bfd940 in ospoll_wait (ospoll=0x559eb9ce30, timeout=timeout@entry=-1) at ../../os/ospoll.c:657
#8  0x0000005579bfb078 in InputThreadDoWork (arg=<optimized out>) at ../../os/inputthread.c:369
#9  0x0000007f957c651c in start_thread (arg=0x7fec380d4f) at pthread_create.c:477
#10 0x0000007f9571d88c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78

Ctrl按键抬起时的调用栈信息:
Thread 18 "InputThread" hit Breakpoint 3, GetKeyboardEvents (events=0x7f95242010, pDev=pDev@entry=0x559f0848b0, type=type@entry=3, key_code=key_code@entry=37) at ../../dix/getevents.c:1067
1067    {
(gdb) bt
#0  GetKeyboardEvents (events=0x7f95242010, pDev=pDev@entry=0x559f0848b0, type=type@entry=3, key_code=key_code@entry=37) at ../../dix/getevents.c:1067
#1  0x0000005579ac9d74 in QueueKeyboardEvents (device=device@entry=0x559f0848b0, type=type@entry=3, keycode=keycode@entry=37) at ../../dix/getevents.c:1051
#2  0x0000005579afab30 in xf86PostKeyEventM (device=device@entry=0x559f0848b0, key_code=key_code@entry=37, is_down=is_down@entry=0) at ../../../../hw/xfree86/common/xf86Xinput.c:1423
#3  0x0000005579afab9c in xf86PostKeyboardEvent (device=0x559f0848b0, key_code=37, is_down=0) at ../../../../hw/xfree86/common/xf86Xinput.c:1432
#4  0x0000007f82381e14 in  () at /usr/lib/xorg/modules/input/libinput_drv.so
#5  0x0000007f823829e4 in  () at /usr/lib/xorg/modules/input/libinput_drv.so
#6  0x0000005579bfb22c in InputReady (fd=24, xevents=1, data=0x559ee27cf0) at ../../os/inputthread.c:180
#7  0x0000005579bfd940 in ospoll_wait (ospoll=0x559eb9ce30, timeout=timeout@entry=-1) at ../../os/ospoll.c:657
#8  0x0000005579bfb078 in InputThreadDoWork (arg=<optimized out>) at ../../os/inputthread.c:369
#9  0x0000007f957c651c in start_thread (arg=0x7fec380d4f) at pthread_create.c:477
#10 0x0000007f9571d88c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78

按住Ctrl按键,然后滚动鼠标滚轮时的调用栈信息如下:

代码块
Thread 1 "X" hit Breakpoint 3, GetKeyboardEvents (events=0x7f94d4f010, pDev=0x559eba1450, type=type@entry=2, key_code=37) at ../../dix/getevents.c:1067
1067    {
(gdb) bt
#0  GetKeyboardEvents (events=0x7f94d4f010, pDev=0x559eba1450, type=type@entry=2, key_code=37) at ../../dix/getevents.c:1067
#1  0x0000005579b439bc in ProcXTestFakeInput (client=0x559f0c84b0) at ../../Xext/xtest.c:423
#2  0x0000005579ab23e0 in Dispatch () at ../../dix/dispatch.c:478
#3  0x0000005579ab650c in dix_main (argc=11, argv=0x7fec380fe8, envp=<optimized out>) at ../../dix/main.c:276
#4  0x0000007f9566cd90 in __libc_start_main (main=
    0x5579a9ff30 <main>, argc=11, argv=0x7fec380fe8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=<optimized out>) at ../csu/libc-start.c:308
#5  0x0000005579a9ff68 in _start () at ../../Xext/xtest.c:538

对比上面两种情况下,GetKeyboardEvents的调用栈信息发现,在异常情况下走的是ProcXTestFakeInput流程。会产生额外的模拟输入事件。修改xtest.c文件进行测试验证,在ProcXTestFakeInput函数中,将type为KeyPress和KeyRelease的event直接return掉。

xtest.pngImage Added

测试操作x11窗口,按住Ctrl按键滚动鼠标滚轮时没有再收到Ctrl按键抬起事件。结果说明xserver确实有向Client端发送额外的模拟输入事件。接下来分析排查xserver处理的键盘模拟输入事件的发送方到底是谁。

继续gdb调试Xorg进程,在ProcXTestFakeInput函数设置断点,按住Ctrl按键滚动鼠标滚轮复现问题。

调试分析结果如下图所示:

...

这里找到了Ctrl按键up伪事件的来源为imwheel程序。imwheel进程使用XTEST扩展Xorg发送模拟事件。包名为imwheel,程序路径/usr/bin/imwheel。将imwheel进程kill掉测试验证结果:按住Ctrl按键滚动鼠标滚轮x11窗口不再重复收到Ctrl按键抬起事件。测试weston应用方式启动的OpenFDE鼠标滚轮模拟双指触摸缩放功能恢复正常。

6、imwheel分析研究

imwheel:是在Linux中支持鼠标非标准按钮的一个程序,用于Linux系统的鼠标滚轮增强工具,它可以重新映射滚轮事件,以提供更好的滚动控制和自定义功能,如缩放、翻页等。事件传递流程如下图所示。

...

最后通过对imwheel项目源码及配置文件的分析,可以通过imwheel -k -b "0 0 0 0 8 9"命令跳过鼠标滚轮抓取。修改fde_ctrl项目的fde_utils文件,在OpenFDE的启动脚本中增加上面的imwheel设置命令。

...