Как получить абсолютные координаты сенсорной панели?

Как получить абсолютные координаты сенсорной панели?

Насколько я понимаю, в более ранних версиях драйвера 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);

Связанный контент