[core/input] clear previous input registrations

make sure that for a given event (widget/object/module, whatever), only
a *single* input event per button can be registered at one time.

the problem otherwise is with modules that re-register their widgets
with the same IDs (cmus, spotify, etc.): Each time the widget is
re-created (each intervall, typically), it re-registers an input event,
creating an always longer list of callbacks being executed when the
button is clicked (not speaking of the memory leak this introduces).

fixes #668
This commit is contained in:
tobi-wan-kenobi 2020-06-29 07:44:22 +02:00
parent 6839e81342
commit 9136ebd321
3 changed files with 6 additions and 2 deletions

View file

@ -8,6 +8,9 @@ def register(event, callback, *args, **kwargs):
__callbacks.setdefault(event, []).append(cb) __callbacks.setdefault(event, []).append(cb)
def unregister(event):
if event in __callbacks:
del __callbacks[event]
def clear(): def clear():
__callbacks.clear() __callbacks.clear()

View file

@ -50,6 +50,7 @@ def __execute(event, cmd, wait=False):
def register(obj, button=None, cmd=None, wait=False): def register(obj, button=None, cmd=None, wait=False):
event_id = __event_id(obj.id if obj is not None else "", button) event_id = __event_id(obj.id if obj is not None else "", button)
logging.debug("registering callback {}".format(event_id)) logging.debug("registering callback {}".format(event_id))
core.event.unregister(event_id) # make sure there's always only one input event
if callable(cmd): if callable(cmd):
core.event.register(event_id, cmd) core.event.register(event_id, cmd)
else: else:

View file

@ -59,14 +59,14 @@ def test_different_events(obj, obj2, cb, cb2):
cb2.assert_not_called() cb2.assert_not_called()
def test_multiple_registrations(obj, cb, cb2): def test_multiple_registrations_on_same_button(obj, cb, cb2):
core.input.register(obj, event(obj)["button"], cb) core.input.register(obj, event(obj)["button"], cb)
core.input.register(obj, event(obj)["button"], cb2) core.input.register(obj, event(obj)["button"], cb2)
core.input.trigger(event(obj)) core.input.trigger(event(obj))
cb.assert_called_once_with(event(obj))
cb2.assert_called_once_with(event(obj)) cb2.assert_called_once_with(event(obj))
cb.assert_not_called()
def test_event_names(): def test_event_names():