test-kivy-app/kivy_venv/lib/python3.11/site-packages/kivy/input/postproc/tripletap.py
2024-09-15 15:12:16 +03:00

107 lines
3.4 KiB
Python

'''
Triple Tap
==========
.. versionadded:: 1.7.0
Search touch for a triple tap
'''
__all__ = ('InputPostprocTripleTap', )
from time import time
from kivy.config import Config
from kivy.vector import Vector
class InputPostprocTripleTap(object):
'''
InputPostProcTripleTap is a post-processor to check if
a touch is a triple tap or not.
Triple tap can be configured in the Kivy config file::
[postproc]
triple_tap_time = 250
triple_tap_distance = 20
The distance parameter is in the range 0-1000 and time is in milliseconds.
'''
def __init__(self):
dist = Config.getint('postproc', 'triple_tap_distance')
self.triple_tap_distance = dist / 1000.0
time = Config.getint('postproc', 'triple_tap_time')
self.triple_tap_time = time / 1000.0
self.touches = {}
def find_triple_tap(self, ref):
'''Find a triple tap touch within *self.touches*.
The touch must be not be a previous triple tap and the distance
must be within the bounds specified. Additionally, the touch profile
must be the same kind of touch.
'''
ref_button = None
if 'button' in ref.profile:
ref_button = ref.button
for touchid in self.touches:
if ref.uid == touchid:
continue
etype, touch = self.touches[touchid]
if not touch.is_double_tap:
continue
if etype != 'end':
continue
if touch.is_triple_tap:
continue
distance = Vector.distance(
Vector(ref.sx, ref.sy),
Vector(touch.osx, touch.osy))
if distance > self.triple_tap_distance:
continue
if touch.is_mouse_scrolling or ref.is_mouse_scrolling:
continue
touch_button = None
if 'button' in touch.profile:
touch_button = touch.button
if touch_button != ref_button:
continue
touch.triple_tap_distance = distance
return touch
def process(self, events):
if self.triple_tap_distance == 0 or self.triple_tap_time == 0:
return events
# first, check if a touch down have a triple tap
for etype, touch in events:
if not touch.is_touch:
continue
if etype == 'begin':
triple_tap = self.find_triple_tap(touch)
if triple_tap:
touch.is_double_tap = False
touch.is_triple_tap = True
tap_time = touch.time_start - triple_tap.time_start
touch.triple_tap_time = tap_time
distance = triple_tap.triple_tap_distance
touch.triple_tap_distance = distance
# add the touch internally
self.touches[touch.uid] = (etype, touch)
# second, check if up-touch is timeout for triple tap
time_current = time()
to_delete = []
for touchid in self.touches.keys():
etype, touch = self.touches[touchid]
if etype != 'end':
continue
if time_current - touch.time_start < self.triple_tap_time:
continue
to_delete.append(touchid)
for touchid in to_delete:
del self.touches[touchid]
return events