如何獲得觸控板的絕對座標

如何獲得觸控板的絕對座標

據我了解,Ubuntu 中 Synaptic 驅動程式的早期版本具有觸控板的“絕對模式”,可讓使用者存取絕對座標和相對座標。然而,Synaptic 決定刪除它(不知道為什麼)並且它不再可用。有沒有辦法在 Ubuntu 20.04 LTS 中存取絕對模式?我希望能夠在 C/C++ 程式中取得這些座標,但對任何其他解決方案開放(Rust、shell 腳本,任何有效的方法)。我也遇到過類似的帖子,但仍然找不到滿意的解決方案。大多數人推薦 evtest 驅動程序,它支援絕對模式,但缺乏其他功能(2 個手指滾動等)。我想恢復到舊版本的 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

現在您輸出timestampcode,但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);

相關內容