You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Description
pynput does not register scroll actions from a touchpad using the ASUS Precision Touchpad Driver. I've confirmed this and the following POC does register the scroll events.
Platform and pynput version
Windows 11, version 23H2, pynput version 1.7.7
To Reproduce
frompynputimportmousedefon_move(x, y):
print('Pointer moved to {0}'.format(
(x, y)))
defon_click(x, y, button, pressed):
print('{0} at {1}'.format(
'Pressed'ifpressedelse'Released',
(x, y)))
ifnotpressed:
# Stop listenerreturnFalsedefon_scroll(x, y, dx, dy):
print('Scrolled {0} at {1}'.format(
'down'ifdy<0else'up',
(x, y)))
# Collect events until releasedwithmouse.Listener(
on_move=on_move,
on_click=on_click,
on_scroll=on_scroll) aslistener:
listener.join()
On ASUS Zenbook with ASUS Precision Touchpad v16.0.0.11
Functional POC Code to register scroll events
importwin32apiimportwin32guiimportwin32conimportctypesfromctypesimportwintypes# Define WM_INPUT manuallyWM_INPUT=0x00FFclassTouchpadListener:
def__init__(self):
self.hInstance=win32api.GetModuleHandle(None)
self.className='TouchpadEventListener'wndClass=win32gui.WNDCLASS()
wndClass.style=win32con.CS_HREDRAW|win32con.CS_VREDRAWwndClass.lpfnWndProc=self.wndProcwndClass.hInstance=self.hInstancewndClass.hCursor=win32gui.LoadCursor(None, win32con.IDC_ARROW)
wndClass.hbrBackground=win32con.COLOR_WINDOWwndClass.lpszClassName=self.classNametry:
win32gui.RegisterClass(wndClass)
exceptwin32gui.error:
pass# The window class is already registeredself.hWnd=win32gui.CreateWindow(
self.className,
'ASUS Precision Touchpad Listener',
0,
0, 0,
win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT,
None, None,
self.hInstance,
None
)
# Register for raw input from the touchpadself.register_raw_input_devices()
defregister_raw_input_devices(self):
classRAWINPUTDEVICE(ctypes.Structure):
_fields_= [
('usUsagePage', ctypes.c_ushort),
('usUsage', ctypes.c_ushort),
('dwFlags', ctypes.c_ulong),
('hwndTarget', ctypes.c_void_p),
]
RIDEV_INPUTSINK=0x00000100HID_USAGE_PAGE_DIGITIZER=0x0DHID_USAGE_DIGITIZER_TOUCHPAD=0x05rid=RAWINPUTDEVICE()
rid.usUsagePage=HID_USAGE_PAGE_DIGITIZERrid.usUsage=HID_USAGE_DIGITIZER_TOUCHPADrid.dwFlags=RIDEV_INPUTSINKrid.hwndTarget=self.hWnduser32=ctypes.WinDLL('user32', use_last_error=True)
RegisterRawInputDevices=user32.RegisterRawInputDevicesRegisterRawInputDevices.argtypes= [ctypes.POINTER(RAWINPUTDEVICE), ctypes.c_uint, ctypes.c_uint]
RegisterRawInputDevices.restype=ctypes.c_boolifnotRegisterRawInputDevices(ctypes.byref(rid), 1, ctypes.sizeof(rid)):
raisectypes.WinError(ctypes.get_last_error())
defwndProc(self, hWnd, msg, wParam, lParam):
ifmsg==WM_INPUT:
self.process_raw_input(lParam)
return0elifmsg==win32con.WM_DESTROY:
win32gui.PostQuitMessage(0)
return0returnwin32gui.DefWindowProc(hWnd, msg, wParam, lParam)
defprocess_raw_input(self, lParam):
user32=ctypes.WinDLL('user32', use_last_error=True)
# Define missing typesHRAWINPUT=ctypes.c_void_pUINT=ctypes.c_uintclassRAWINPUTHEADER(ctypes.Structure):
_fields_= [
('dwType', UINT),
('dwSize', UINT),
('hDevice', ctypes.c_void_p),
('wParam', ctypes.c_ulong),
]
classRAWMOUSE(ctypes.Structure):
_fields_= [
('usFlags', ctypes.c_ushort),
('ulButtons', ctypes.c_ulong),
('usButtonFlags', ctypes.c_ushort),
('usButtonData', ctypes.c_ushort),
('ulRawButtons', ctypes.c_ulong),
('lLastX', ctypes.c_long),
('lLastY', ctypes.c_long),
('ulExtraInformation', ctypes.c_ulong),
]
classRAWKEYBOARD(ctypes.Structure):
_fields_= [
('MakeCode', ctypes.c_ushort),
('Flags', ctypes.c_ushort),
('Reserved', ctypes.c_ushort),
('VKey', ctypes.c_ushort),
('Message', ctypes.c_uint),
('ExtraInformation', ctypes.c_ulong),
]
classRAWHID(ctypes.Structure):
_fields_= [
('dwSizeHid', ctypes.c_uint),
('dwCount', ctypes.c_uint),
('bRawData', ctypes.c_byte*1), # Placeholder
]
classRAWINPUT_UNION(ctypes.Union):
_fields_= [
('mouse', RAWMOUSE),
('keyboard', RAWKEYBOARD),
('hid', RAWHID),
]
classRAWINPUT(ctypes.Structure):
_fields_= [
('header', RAWINPUTHEADER),
('data', RAWINPUT_UNION),
]
GetRawInputData=user32.GetRawInputDataGetRawInputData.argtypes= [
HRAWINPUT, # hRawInputUINT, # uiCommandctypes.c_void_p, # pDatactypes.POINTER(UINT), # pcbSizeUINT# cbSizeHeader
]
GetRawInputData.restype=UINTRID_INPUT=0x10000003data_size=UINT(0)
header_size=ctypes.sizeof(RAWINPUTHEADER)
# First call to get the size of the raw input datares=GetRawInputData(
HRAWINPUT(lParam),
RID_INPUT,
None,
ctypes.byref(data_size),
header_size
)
ifres==-1ordata_size.value==0:
print("Failed to get raw input data size")
return# Allocate buffer for raw input databuffer=ctypes.create_string_buffer(data_size.value)
# Second call to get the raw input datares=GetRawInputData(
HRAWINPUT(lParam),
RID_INPUT,
buffer,
ctypes.byref(data_size),
header_size
)
ifres==-1orres==0:
print("Failed to get raw input data")
return# Cast buffer to RAWINPUT structureraw_input=ctypes.cast(buffer, ctypes.POINTER(RAWINPUT)).contents# Check if the input is from a HID deviceifraw_input.header.dwType==2: # RIM_TYPEHID# Access the HID datahid=raw_input.data.hid# Calculate the size of HID datahid_data_size=hid.dwSizeHid*hid.dwCount# Access the raw HID datahid_data=ctypes.cast(ctypes.byref(hid.bRawData), ctypes.POINTER(ctypes.c_ubyte*hid_data_size)).contents# Process the HID data hereprint("Received touchpad HID event")
else:
print("Received non-HID input")
defrun(self):
win32gui.PumpMessages()
if__name__=='__main__':
listener=TouchpadListener()
listener.run()
The text was updated successfully, but these errors were encountered:
Description
pynput does not register scroll actions from a touchpad using the ASUS Precision Touchpad Driver. I've confirmed this and the following POC does register the scroll events.
Platform and pynput version
Windows 11, version 23H2, pynput version 1.7.7
To Reproduce
On ASUS Zenbook with ASUS Precision Touchpad v16.0.0.11
Functional POC Code to register scroll events
The text was updated successfully, but these errors were encountered: