94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
|
'''
|
||
|
Retain Touch
|
||
|
============
|
||
|
|
||
|
Reuse touch to counter lost finger behavior
|
||
|
'''
|
||
|
|
||
|
__all__ = ('InputPostprocRetainTouch', )
|
||
|
|
||
|
from kivy.config import Config
|
||
|
from kivy.vector import Vector
|
||
|
import time
|
||
|
|
||
|
|
||
|
class InputPostprocRetainTouch(object):
|
||
|
'''
|
||
|
InputPostprocRetainTouch is a post-processor to delay the 'up' event of a
|
||
|
touch, to reuse it under certains conditions. This module is designed to
|
||
|
prevent lost finger touches on some hardware/setups.
|
||
|
|
||
|
Retain touch can be configured in the Kivy config file::
|
||
|
|
||
|
[postproc]
|
||
|
retain_time = 100
|
||
|
retain_distance = 50
|
||
|
|
||
|
The distance parameter is in the range 0-1000 and time is in milliseconds.
|
||
|
'''
|
||
|
|
||
|
def __init__(self):
|
||
|
self.timeout = Config.getint('postproc', 'retain_time') / 1000.0
|
||
|
self.distance = Config.getint('postproc', 'retain_distance') / 1000.0
|
||
|
self._available = []
|
||
|
self._links = {}
|
||
|
|
||
|
def process(self, events):
|
||
|
# check if module is disabled
|
||
|
if self.timeout == 0:
|
||
|
return events
|
||
|
|
||
|
d = time.time()
|
||
|
for etype, touch in events[:]:
|
||
|
if not touch.is_touch:
|
||
|
continue
|
||
|
if etype == 'end':
|
||
|
events.remove((etype, touch))
|
||
|
if touch.uid in self._links:
|
||
|
selection = self._links[touch.uid]
|
||
|
selection.ud.__pp_retain_time__ = d
|
||
|
self._available.append(selection)
|
||
|
del self._links[touch.uid]
|
||
|
else:
|
||
|
touch.ud.__pp_retain_time__ = d
|
||
|
self._available.append(touch)
|
||
|
elif etype == 'update':
|
||
|
if touch.uid in self._links:
|
||
|
selection = self._links[touch.uid]
|
||
|
selection.x = touch.x
|
||
|
selection.y = touch.y
|
||
|
selection.sx = touch.sx
|
||
|
selection.sy = touch.sy
|
||
|
events.remove((etype, touch))
|
||
|
events.append((etype, selection))
|
||
|
else:
|
||
|
pass
|
||
|
elif etype == 'begin':
|
||
|
# new touch, found the nearest one
|
||
|
selection = None
|
||
|
selection_distance = 99999
|
||
|
for touch2 in self._available:
|
||
|
touch_distance = Vector(touch2.spos).distance(touch.spos)
|
||
|
if touch_distance > self.distance:
|
||
|
continue
|
||
|
if touch2.__class__ != touch.__class__:
|
||
|
continue
|
||
|
if touch_distance < selection_distance:
|
||
|
# eligible for continuation
|
||
|
selection_distance = touch_distance
|
||
|
selection = touch2
|
||
|
if selection is None:
|
||
|
continue
|
||
|
|
||
|
self._links[touch.uid] = selection
|
||
|
self._available.remove(selection)
|
||
|
events.remove((etype, touch))
|
||
|
|
||
|
for touch in self._available[:]:
|
||
|
t = touch.ud.__pp_retain_time__
|
||
|
if d - t > self.timeout:
|
||
|
self._available.remove(touch)
|
||
|
events.append(('end', touch))
|
||
|
|
||
|
return events
|