Насколько я понимаю, в более ранних версиях драйвера Synaptic в Ubuntu был «абсолютный режим» для трекпада, который позволял пользователю получать доступ как к абсолютным, так и к относительным координатам. Однако Synaptic решила удалить его (не знаю почему), и теперь он недоступен. Есть ли способ получить доступ к абсолютному режиму в Ubuntu 20.04 LTS? Я хотел бы иметь возможность получать эти координаты в программе на C/C++, но открыт для любых других решений (Rust, скрипт оболочки, что бы ни работало). Я натыкался на похожие сообщения, но все еще не могу найти удовлетворительного решения. Большинство рекомендуют драйвер evtest, который поддерживает абсолютный режим, но не имеет других функций (прокрутка двумя пальцами и т. д.). Я думаю, что возврат к более старой версии драйвера Synaptic может помочь, но хотел бы узнать, что я упущу. Я имею в виду, есть ли какие-либо важные функции в более новом драйвере Synaptic, которых нет в старом с абсолютным режимом?
Редактировать: Я немного покопался и наткнулся на эту страницу -->http://manpages.ubuntu.com/manpages/bionic/man1/python-evdev.1.html
Он показывает, как использовать библиотеку Python, evdev, и как использовать ее для доступа к событиям системного ввода. Следуя примерам, я настроил его на отслеживание событий моего трекпада, и при перемещении пальца я получил целую стену информации, которую, к сожалению, я не понял. Я заметил такие термины, как ABS_X, ABS_Y, но не смог ничего из этого сделать. Несмотря на это, похоже, что я могу получить доступ к большому количеству информации о трекпаде через эту библиотеку, включая что-то, связанное с абсолютными координатами. Как мне использовать эту информацию? Может ли кто-нибудь показать мне, как написать простую функцию Python с помощью evdev
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, но, похоже, избавление от нее выводит на экран то, что вам нужно: необработанные координаты 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, и это хакерское решение, но работает. работает только в 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);