Last active
October 5, 2022 05:29
-
-
Save zalo/8ca3d2a758d0dae34b40316e29211be2 to your computer and use it in GitHub Desktop.
Python Windows Multitouch Interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ctypes import * | |
from ctypes.wintypes import * | |
# Constants | |
# For touchMask | |
TOUCH_MASK_NONE= 0x00000000 # Default | |
TOUCH_MASK_CONTACTAREA= 0x00000001 | |
TOUCH_MASK_ORIENTATION= 0x00000002 | |
TOUCH_MASK_PRESSURE= 0x00000004 | |
TOUCH_MASK_ALL= 0x00000007 | |
# For touchFlag | |
TOUCH_FLAG_NONE= 0x00000000 | |
# For pointerType | |
PT_POINTER= 0x00000001 # All | |
PT_TOUCH= 0x00000002 | |
PT_PEN= 0x00000003 | |
PT_MOUSE= 0x00000004 | |
#For pointerFlags | |
POINTER_FLAG_NONE= 0x00000000 # Default | |
POINTER_FLAG_NEW= 0x00000001 | |
POINTER_FLAG_INRANGE= 0x00000002 | |
POINTER_FLAG_INCONTACT= 0x00000004 | |
POINTER_FLAG_FIRSTBUTTON= 0x00000010 | |
POINTER_FLAG_SECONDBUTTON=0x00000020 | |
POINTER_FLAG_THIRDBUTTON= 0x00000040 | |
POINTER_FLAG_FOURTHBUTTON=0x00000080 | |
POINTER_FLAG_FIFTHBUTTON= 0x00000100 | |
POINTER_FLAG_PRIMARY= 0x00002000 | |
POINTER_FLAG_CONFIDENCE= 0x00004000 | |
POINTER_FLAG_CANCELED= 0x00008000 | |
POINTER_FLAG_DOWN= 0x00010000 | |
POINTER_FLAG_UPDATE= 0x00020000 | |
POINTER_FLAG_UP= 0x00040000 | |
POINTER_FLAG_WHEEL= 0x00080000 | |
POINTER_FLAG_HWHEEL= 0x00100000 | |
POINTER_FLAG_CAPTURECHANGED=0x00200000 | |
# Structs Needed | |
class POINTER_INFO(Structure): | |
_fields_=[("pointerType",c_uint32), | |
("pointerId",c_uint32), | |
("frameId",c_uint32), | |
("pointerFlags",c_int), | |
("sourceDevice",HANDLE), | |
("hwndTarget",HWND), | |
("ptPixelLocation",POINT), | |
("ptHimetricLocation",POINT), | |
("ptPixelLocationRaw",POINT), | |
("ptHimetricLocationRaw",POINT), | |
("dwTime",DWORD), | |
("historyCount",c_uint32), | |
("inputData",c_int32), | |
("dwKeyStates",DWORD), | |
("PerformanceCount",c_uint64), | |
("ButtonChangeType",c_int) | |
] | |
class POINTER_TOUCH_INFO(Structure): | |
_fields_=[("pointerInfo",POINTER_INFO), | |
("touchFlags",c_int), | |
("touchMask",c_int), | |
("rcContact", RECT), | |
("rcContactRaw",RECT), | |
("orientation", c_uint32), | |
("pressure", c_uint32)] | |
# Initialize Pointer and Touch info | |
def initialize(maxtouches=10, dwmode=1): | |
global touches | |
touches = (POINTER_TOUCH_INFO * maxtouches)() | |
for ind in range(maxtouches): | |
pointerInfo=POINTER_INFO(pointerType = PT_TOUCH, | |
pointerId = ind, | |
ptPixelLocation = POINT(950,540), | |
pointerFlags = POINTER_FLAG_NEW) | |
touchInfo=POINTER_TOUCH_INFO(pointerInfo = pointerInfo, | |
touchFlags = TOUCH_FLAG_NONE, | |
touchMask = TOUCH_MASK_ALL, | |
rcContact = RECT(pointerInfo.ptPixelLocation.x-5, | |
pointerInfo.ptPixelLocation.y-5, | |
pointerInfo.ptPixelLocation.x+5, | |
pointerInfo.ptPixelLocation.y+5), | |
orientation = 90, | |
pressure = 32000) | |
touches[ind] = touchInfo | |
if (windll.user32.InitializeTouchInjection(len(touches), 1) != 0): | |
print("Initialized Touch Injection") | |
ids_to_update = 0 | |
currently_down = None | |
def updateTouchInfo(id, down, x = 0, y = 0, fingerRadius=1, orientation = 90, pressure = 32000): | |
global currently_down, ids_to_update | |
if currently_down == None or len(currently_down) != len(touches): | |
currently_down = [False] * len(touches) | |
if down: | |
touches[id].pointerInfo.pointerFlags = (((POINTER_FLAG_DOWN) if not currently_down[id] else POINTER_FLAG_UPDATE)| | |
POINTER_FLAG_INRANGE | | |
POINTER_FLAG_INCONTACT) | |
touches[id].orientation = orientation | |
touches[id].pressure = pressure | |
touches[id].pointerInfo.ptPixelLocation.x = x | |
touches[id].pointerInfo.ptPixelLocation.y = y | |
touches[id].rcContact.left = x - fingerRadius | |
touches[id].rcContact.right = x + fingerRadius | |
touches[id].rcContact.top = y - fingerRadius | |
touches[id].rcContact.bottom = y + fingerRadius | |
else: | |
touches[id].pointerInfo.pointerFlags = POINTER_FLAG_UP #if currently_down[id] else POINTER_FLAG_UPDATE #if currently_down[id] else POINTER_FLAG_UPDATE | |
ids_to_update += 1 if down or currently_down[id] else 0 | |
currently_down[id] = down | |
def applyTouches(): | |
global ids_to_update | |
if ids_to_update > 0: | |
if (windll.user32.InjectTouchInput(int(ids_to_update), byref(touches[0])) == 0): | |
print("Failed trying to update", ids_to_update, "points with Error:", FormatError()) | |
ids_to_update = 0 | |
# Use like: | |
#import multitouch # Call once | |
#multitouch.initialize() # Call once | |
#for i in range(10): # Call every frame | |
# if i < len(keypoints): | |
# multitouch.updateTouchInfo(i, True, | |
# int(keypoints[i].pt[0] * 3), | |
# int(keypoints[i].pt[1] * 3), | |
# int(keypoints[i].size / 2)) | |
# else: | |
# multitouch.updateTouchInfo(i, False) | |
#multitouch.applyTouches() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment