看起来像是一个 bug

看起来像是一个 bug

看起来像是一个 bug

好的,我相信这是 xorg evdev 驱动程序中的一个错误,但由于 ubuntu-bug for precise 如此好心地要求我通过支持渠道解决这个问题,我首先在这里报告了这个问题。与此同时,我升级到了 quantal 并报告了一个正确的错误,但如果支持社区的某个人有答案,那也不会有什么问题。(本段已编辑,以提及已报告错误

设置

这是连接到 Acer T231H 多点触控显示器的 Ubuntu 12.04 精确版。实际上,我在多个操作系统设置中都遇到过这种情况,其中一个是通过 debootstrap 完成的。涉及的软件包:

  • xserver-xorg-input-evdev 1:2.7.0-0ubuntu1
  • 一个系统上是 linux-image-*-generic 3.2.0-24.39,另一个系统上是 3.2.0-25

症状

X 发送给应用程序的鼠标事件不一致。可以使用 xev 进行调试。

第一次触摸屏幕之前会有一个 MotionNotify 事件,该事件的状态已经为 0x100,即按下鼠标左键。之后是 ButtonPress 事件,状态同样为 0x100,尽管该值应该指示按钮的状态事件发生。后续的拖动没有问题,ButtonRelease也没有问题,但是状态值中的0x100位永远不会再变为零。

即使我还连接了普通鼠标,它也会报告每次移动,就好像我按住了鼠标左键一样。我能找到的唯一解决办法是重新启动 X 服务器。与 ButtonPress 和 ButtonRelease 事件一起,鼠标左键的这个常量位相当于按钮状态报告不一致。

例如,由于此问题,Java 应用程序会将每次移动都报告为拖延,对焦点管理产生严重影响。这使得使用应用程序的不同部分几乎不可能,因为鼠标移动只会报告给鼠标进入应用程序窗口的组件。

预期行为与实际行为的比较

预期行为:

  1. 带状态的 MotionNotify0x000拖动普通鼠标时
  2. 带状态的 MotionNotify0x000触摸前移动,或者根本没有事件
  3. 触摸屏幕时,按钮按下状态为 0x000
  4. 拖动手指时,MotionNotify 状态为 0x100
  5. 抬起手指时,ButtonRelease 状态为 0x100
  6. 带状态的 MotionNotify0x000随后拖动普通鼠标

实际行为:

  1. 在第一次触摸之前拖动普通鼠标时,MotionNotify 状态为 0x000
  2. 带状态的 MotionNotify0x100用于 ButtonPress 事件之前
  3. 带状态的 ButtonPress0x100触摸屏幕时
  4. 拖动手指时,MotionNotify 状态为 0x100
  5. 抬起手指时,ButtonRelease 状态为 0x100
  6. 带状态的 MotionNotify0x100随后拖动普通鼠标

答案1

我自己解决了这个问题

主要错误分析

我仔细研究了 evdev 和核心 x 服务器的源代码。结果发现这个错误并不在 evdev 中,而是在 xserver-xorg-core 中。在那里提交(这也是包含在 Xorg 上游TOUCH_END)删除了唯一一段设置事件标志的代码。如果没有此标志,UpdateDeviceState 不会从状态中移除按钮,从而导致我最初问题中的“按钮始终被按下”行为。只需恢复该提交即可恢复主要核心事件功能,即按钮在事件发生后立即被标记为已释放ButtonRelease

鼠标按下事件的小错误

但是,输出中仍然存在一个问题xevButtonPress事件已经有了state 0x100,但状态应该反映鼠标按钮的状态事件发生。这似乎是由于处理触摸序列所有权变更的方式所致。一点在该所有权管理代码中,使用 重放触摸历史记录TouchEventHistoryReplay,但设备的内部状态未设置为重放之前的状态。我尚未为此制定补丁。当我制定补丁时,我会将其附加到错误报告。我认为即使没有针对该小问题的补丁,这里也已经回答了这个问题,因为这是一个单独的问题。

如何调试

如果有人读到这篇文章时遇到类似的问题:我曾考虑过使用 gdb,但我不确定如果调试器中的 X 服务器停止,我是否能够正确切换 vt,而且我在该机器上没有配置可用的 ssh 服务器。因此,我使用了有史以来最古老的调试辅助工具之一,并在ErrorF整个代码中随意分散调用,Xi/exevents.c特别是。然后我重新编译了代码(我最初使用拆除) 而不安装它,然后以 root 身份运行已编译的二进制文件 ( build-main/hw/xfree86/Xorg),如下所示:

$ make -C build-main
$ sudo -s
# apt-get install openbox
# ( sleep 3; DISPLAY=:1 exec openbox; ) & build-main/hw/xfree86/Xorg :1

这将重新编译代码(即使是很小的修改也需要很长时间,因此 makefile 中的依赖项管理似乎不是最理想的,但我不想深入研究这一点)。然后在成为 root 后,它会启动新的 X 服务器,并在几分钟后在该服务器上启动 openbox。请注意,您将以 root 身份运行 openbox,因此这仅用于测试。

相关内容