![如何获取触摸板的绝对坐标](https://linux22.com/image/1070801/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E8%A7%A6%E6%91%B8%E6%9D%BF%E7%9A%84%E7%BB%9D%E5%AF%B9%E5%9D%90%E6%A0%87.png)
据我所知,Ubuntu 中 Synaptic 驱动程序的早期版本为触控板提供了“绝对模式”,允许用户访问绝对坐标和相对坐标。然而,Synaptic 决定删除它(不确定原因)并且它不再可用。有没有办法在 Ubuntu 20.04 LTS 中访问绝对模式?我希望能够在 C/C++ 程序中获取这些坐标,但也接受任何其他解决方案(Rust、shell 脚本,任何可行的解决方案)。我遇到过类似的帖子,但我仍然找不到令人满意的解决方案。大多数人推荐 evtest 驱动程序,它确实支持绝对模式,但缺少其他功能(两指滚动等)。我想恢复到旧版本的 Synaptic 驱动程序可能会有所帮助,但我想知道我会错过什么。我的意思是,较新的 Synaptic 驱动程序中是否有任何重要的功能是旧的绝对模式驱动程序所没有的?
编辑:我做了更多的挖掘并偶然发现了这个页面-->http://manpages.ubuntu.com/manpages/bionic/man1/python-evdev.1.html
它展示了如何使用 Python 库 evdev,以及如何使用它来访问系统输入事件。按照示例,我将其设置为监视我的触控板事件,当我移动手指时,我得到了一大堆信息,但不幸的是,我不明白。我确实注意到了 ABS_X、ABS_Y 等术语,但无法理解。无论如何,似乎我可以通过这个库访问很多触控板信息,包括与绝对坐标有关的信息。我如何使用这些信息?有人可以告诉我如何使用 evdev 编写一个简单的 Python 函数吗
def foo():
...
return (x,y)
其中 (x,y) 代表我的手指在触控板上的位置?
编辑 2:evdev 监控我的触控板的示例输出。这些可以用来获取绝对坐标吗?
absolute axis event at 1623586006.216310, ABS_MT_TRACKING_ID
absolute axis event at 1623586006.216310, ABS_MT_POSITION_X
absolute axis event at 1623586006.216310, ABS_MT_POSITION_Y
absolute axis event at 1623586006.216310, ABS_MT_PRESSURE
key event at 1623586006.216310, 330 (BTN_TOUCH), down
absolute axis event at 1623586006.216310, ABS_X
absolute axis event at 1623586006.216310, ABS_Y
absolute axis event at 1623586006.216310, ABS_PRESSURE
key event at 1623586006.216310, 325 (BTN_TOOL_FINGER), down
synchronization event at 1623586006.216310, SYN_REPORT
absolute axis event at 1623586006.231209, ABS_MT_PRESSURE
absolute axis event at 1623586006.231209, ABS_PRESSURE
答案1
使用
>>> print(event)
event at 1337197425.477827, code 04, type 04, val 458792
现在你输出timestamp
和code
,但val
应该是你的坐标,见https://python-evdev.readthedocs.io/en/latest/_modules/evdev/events.html。
答案2
抱歉回复迟了。希望这至少能有所帮助。不管怎样,我一直在想办法。如果你按照你发布的链接上的“教程”操作,你很可能就会得到类似的结果print(evdev.categorize(event))
。
现在我不知道 categorize 是做什么的,但是摆脱 categorize 函数似乎可以打印出您要查找的内容;原始 x 和 y 位置。
from evdev import InputDevice
device = InputDevice('/dev/input/event8')
for event in device.read_loop():
print(event)
输出event
如下:
event at 1664686111.342840, code 53, type 03, val 1097
event at 1664686111.342840, code 54, type 03, val 736
event at 1664686111.342840, code 00, type 03, val 1097
event at 1664686111.342840, code 01, type 03, val 736
event at 1664686111.342840, code 05, type 04, val 201000
代码 53 和 54 似乎包含正确的数据。至少对我来说是这样。不过,您可能需要自己做一些推理才能弄清楚。我不知道您的触摸板在 evdev 中的工作方式是否与我的一样,所以这可能根本行不通。
我会很快给出一些代码供您复制和粘贴:
from evdev import InputDevice
#SET THIS TO YOUR DEVICE
device = InputDevice('/dev/input/event8')
x = 0
y = 0
def get_xy_coords(e):
#you may need to change this number here; i don't know
if e.code == 53:
global x
x = e.value
#this one too
if e.code == 54:
global y
y = e.value
for event in device.read_loop():
get_xy_coords(event)
这里。此确切代码将在每次读取循环中将 x 和 y 设置为其各自的坐标。希望我能帮到你,尽管一年后才发布这篇文章。
答案3
根据@Greyson Phipps 的回答,我创建了一个简单的脚本,使触摸板像绘图板一样运行。 https://github.com/Vaisakhkm2625/touchpaddraw
不太理想,因为我并不是一个主要的 Python 开发人员,而且这是一个 hacky 解决方案,但有效。仅在 xorg.in wayland(gnome)中有效,这会得到 2 个游标,一个是绝对游标,一个是相对游标,并且在它们之间跳跃......
import math
import os
import time
#get trackpad absolute coords
from evdev import InputDevice
import argparse
from pynput import mouse
from pynput.mouse import Button
# Initialize parser
parser = argparse.ArgumentParser()
# Adding optional argument
parser.add_argument("-d", "--device", help = "device (event*)")
# Read arguments from command line
args = parser.parse_args()
#SET THIS TO YOUR DEVICE
device = InputDevice('/dev/input/'+ args.device if args.device else 'event7')
touchpad_x_max = 1224
touchpad_y_max = 804
max_x = 1920
max_y = 1080
x = 0
y = 0
def get_xy_coords(e):
#you may need to change this number here; i don't know
if e.code == 53:
global x
x = e.value
#this one too
if e.code == 54:
global y
y = e.value
def mapFromTo(x,a,b,c,d):
# y=(x-a)//(b-a)*(d-c)+c
y=(x-a)/(b-a)*(d-c)+c
return y
x_pos =0
y_pos =0
mouse_controller = mouse.Controller()
for event in device.read_loop():
#rows, cols = stdscr.getmaxyx()
get_xy_coords(event)
if event.code == 54:
prev_x_pos = x_pos
prev_y_pos = y_pos
x_pos =math.floor(mapFromTo(x,0,touchpad_x_max,0,max_x))
y_pos =math.floor(mapFromTo(y,0,touchpad_y_max,0,max_y))
if (abs(prev_x_pos-x_pos)>15 or abs(prev_y_pos-y_pos)>15):
mouse_controller.release(Button.left)
mouse_controller.position = (x_pos,y_pos);
mouse_controller.press(Button.left)
mouse_controller.position = (x_pos,y_pos);