evdev 是如何判断是否移动 x11 光标的?
How does evdev determine whether or not to move the x11 cursor?
我开始深入研究 linux 上的 evdev api 以尝试使用 uinput 仿真。我注意到在操纵杆和触摸板之间,有不同的 button/key 事件代码来区分按下操纵杆按钮和单击鼠标。但是这两种设备都有 ABS_X 和 ABS_Y 轴的事件代码。
joystick dump:
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 128
# Min 0
# Max 255
# Fuzz 0
# Flat 15
# Resolution 0
# Event code 1 (ABS_Y)
# Value 103
# Min 0
# Max 255
# Fuzz 0
# Flat 15
# Resolution 0
touchpad dump:
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 3909
# Min 1270
# Max 5670
# Fuzz 0
# Flat 0
# Resolution 44
# Event code 1 (ABS_Y)
# Value 3835
# Min 1240
# Max 4746
# Fuzz 0
# Flat 0
# Resolution 66
那么 x11 如何知道是将“/dev/input/eventX”节点视为操纵杆还是鼠标来移动屏幕光标?是否有一些 ioctl 可以用来设置设备是否由 x11 加载? driver 还需要做些什么来表明这一点?
我查看了一些错误报告,发现在旧版本中存在连接时游戏手柄确实会移动鼠标的情况,但我找不到任何补丁表明它们更改了什么以表明与 x11 的区别.
在有人说之前,我知道在实践中使用 libevdev 比直接调用 uinput 更可取,但这仅用于教育目的。即使在那里,我也有同样的问题。
所以我浏览了 uinput 模块文档和示例代码。我注意到在他们模拟鼠标的示例代码中,他们通过 ioctl 调用为鼠标左键 (BTN_LEFT
) 添加了一个事件
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
我发现他们包含此事件类型很奇怪,因为他们只是在示例代码中移动(而不是单击)鼠标,并且确实删除了那些 ioctl 导致轴事件不影响 x11 指针。
现在,在他们的示例代码中,他们使用相对轴事件 (REL_X
、REL_Y
) 进行鼠标移动,而不是我所指的绝对事件 (ABS_X
、ABS_Y
).这是因为它们模拟的是实际的鼠标而不是触摸板。但这确实给了我一个提示,即 x11 会查找要在设备位中列出的某些事件类型,以确定它是哪种设备。
为了进一步证实这一理论,我在同一文档的游戏手柄设备检测部分找到了这条注释。 All gamepads that follow the protocol described here map BTN_GAMEPAD. This is an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such.
虽然这并没有明确说明鼠标或触摸板,但它确实支持输入设备上设置的某些事件位用于确定 x11 如何处理来自这些设备的输入的想法。我确实发现,如果您还设置了 BTN_LEFT
位和 REL_X
REL_Y
位,那么创建一个设置了 BTN_GAMEPAD
位的游戏手柄设备仍然可以用作鼠标,所以看起来就像 x11 正在做的只是寻找一些要设置的关键位以将某些东西视为鼠标。
好吧,回到 touchpad/joystick 问题,我还没有弄清楚如何模拟触摸板来准确测试需要设置哪些位才能让 x11 将设备识别为触摸板,不过我怀疑 BTN_TOUCH
事件在其中起作用。无论导致 x11 将设备识别为触摸板并移动指针的事件位组合是什么,按理说这种组合通常不会在游戏手柄上找到,这就是向 x11 表明游戏手柄不应移动光标的原因它有 ABS_X
和 ABS_Y
轴,就像触摸板一样。如果我以后有时间,我会尝试找出确切的组合并更新此解决方案。
我开始深入研究 linux 上的 evdev api 以尝试使用 uinput 仿真。我注意到在操纵杆和触摸板之间,有不同的 button/key 事件代码来区分按下操纵杆按钮和单击鼠标。但是这两种设备都有 ABS_X 和 ABS_Y 轴的事件代码。
joystick dump:
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 128
# Min 0
# Max 255
# Fuzz 0
# Flat 15
# Resolution 0
# Event code 1 (ABS_Y)
# Value 103
# Min 0
# Max 255
# Fuzz 0
# Flat 15
# Resolution 0
touchpad dump:
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 3909
# Min 1270
# Max 5670
# Fuzz 0
# Flat 0
# Resolution 44
# Event code 1 (ABS_Y)
# Value 3835
# Min 1240
# Max 4746
# Fuzz 0
# Flat 0
# Resolution 66
那么 x11 如何知道是将“/dev/input/eventX”节点视为操纵杆还是鼠标来移动屏幕光标?是否有一些 ioctl 可以用来设置设备是否由 x11 加载? driver 还需要做些什么来表明这一点?
我查看了一些错误报告,发现在旧版本中存在连接时游戏手柄确实会移动鼠标的情况,但我找不到任何补丁表明它们更改了什么以表明与 x11 的区别.
在有人说之前,我知道在实践中使用 libevdev 比直接调用 uinput 更可取,但这仅用于教育目的。即使在那里,我也有同样的问题。
所以我浏览了 uinput 模块文档和示例代码。我注意到在他们模拟鼠标的示例代码中,他们通过 ioctl 调用为鼠标左键 (BTN_LEFT
) 添加了一个事件
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
我发现他们包含此事件类型很奇怪,因为他们只是在示例代码中移动(而不是单击)鼠标,并且确实删除了那些 ioctl 导致轴事件不影响 x11 指针。
现在,在他们的示例代码中,他们使用相对轴事件 (REL_X
、REL_Y
) 进行鼠标移动,而不是我所指的绝对事件 (ABS_X
、ABS_Y
).这是因为它们模拟的是实际的鼠标而不是触摸板。但这确实给了我一个提示,即 x11 会查找要在设备位中列出的某些事件类型,以确定它是哪种设备。
为了进一步证实这一理论,我在同一文档的游戏手柄设备检测部分找到了这条注释。 All gamepads that follow the protocol described here map BTN_GAMEPAD. This is an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such.
虽然这并没有明确说明鼠标或触摸板,但它确实支持输入设备上设置的某些事件位用于确定 x11 如何处理来自这些设备的输入的想法。我确实发现,如果您还设置了 BTN_LEFT
位和 REL_X
REL_Y
位,那么创建一个设置了 BTN_GAMEPAD
位的游戏手柄设备仍然可以用作鼠标,所以看起来就像 x11 正在做的只是寻找一些要设置的关键位以将某些东西视为鼠标。
好吧,回到 touchpad/joystick 问题,我还没有弄清楚如何模拟触摸板来准确测试需要设置哪些位才能让 x11 将设备识别为触摸板,不过我怀疑 BTN_TOUCH
事件在其中起作用。无论导致 x11 将设备识别为触摸板并移动指针的事件位组合是什么,按理说这种组合通常不会在游戏手柄上找到,这就是向 x11 表明游戏手柄不应移动光标的原因它有 ABS_X
和 ABS_Y
轴,就像触摸板一样。如果我以后有时间,我会尝试找出确切的组合并更新此解决方案。