1414
1515@dataclass
1616class _DebounceData :
17- t_last : float | None = None
17+ t_last_frame : float = 0
18+ t_last_call : float = 0
1819 timer : threading .Timer | None = None
20+ lock : Lock = None
1921
2022
2123def debounce (arg = None ):
@@ -28,50 +30,37 @@ def debounced(obj, *args, **kwargs):
2830
2931 fname = func .__name__
3032 if obj ._debounce_data .get (fname , None ) is None :
31- obj ._debounce_data [fname ] = _DebounceData (None , None )
33+ obj ._debounce_data [fname ] = _DebounceData (0 , 0 , None , Lock () )
3234
3335 data = obj ._debounce_data [fname ]
36+ t_call = time .time ()
37+ data .t_last_call = t_call
3438
35- # check if we already have a render scheduled
36- if platform .is_pyodide :
37- if data .timer is not None and not data .timer .done ():
38- return
39- else :
40- if data .timer is not None :
41- return
39+ frame_time = 1.0 / target_fps
4240
4341 def f ():
44- # clear the timer, so we can schedule a new one with the next function call
45- t = time .time ()
46- data .timer = None
47- if platform .is_pyodide :
48- # due to async nature, we need to update t_last before calling func
49- data .t_last = t
50- func (obj , * args , ** kwargs )
51- else :
52- data .t_last = t
42+ with data .lock :
43+ if t_call != data .t_last_call and t_call - data .t_last_frame < frame_time :
44+ return
45+
46+ data .t_last_frame = time .time ()
5347 func (obj , * args , ** kwargs )
5448
55- if data .timer is not None :
56- return
49+ t_wait = frame_time - (t_call - data .t_last_frame )
5750
58- if data .t_last is None :
59- # first call -> just call the function immediately
60- data .t_last = time .time ()
51+ if t_wait <= 0 :
6152 f ()
6253 return
6354
64- t_wait = max (1 / target_fps - (time .time () - data .t_last ), 0 )
6555 if platform .is_pyodide :
6656 import asyncio
6757 async def _runner ():
6858 if t_wait > 0 :
6959 await asyncio .sleep (t_wait )
7060 f ()
71- data . timer = asyncio .create_task (_runner ())
61+ asyncio .create_task (_runner ())
7262 else :
73- data .timer = threading .Timer (t_wait , f )
74- data .timer .start ()
63+ threading .Timer (t_wait , f ).start ()
7564
7665 debounced ._original = func
7766 return debounced
0 commit comments