From 9136ebd3211d7b68ce5d4052e616ef4d1d165eb5 Mon Sep 17 00:00:00 2001 From: tobi-wan-kenobi Date: Mon, 29 Jun 2020 07:44:22 +0200 Subject: [PATCH] [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 --- bumblebee_status/core/event.py | 3 +++ bumblebee_status/core/input.py | 1 + tests/core/test_input.py | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bumblebee_status/core/event.py b/bumblebee_status/core/event.py index 88096a5..8e969f0 100644 --- a/bumblebee_status/core/event.py +++ b/bumblebee_status/core/event.py @@ -8,6 +8,9 @@ def register(event, callback, *args, **kwargs): __callbacks.setdefault(event, []).append(cb) +def unregister(event): + if event in __callbacks: + del __callbacks[event] def clear(): __callbacks.clear() diff --git a/bumblebee_status/core/input.py b/bumblebee_status/core/input.py index a2ebaa8..9dbc2a6 100644 --- a/bumblebee_status/core/input.py +++ b/bumblebee_status/core/input.py @@ -50,6 +50,7 @@ def __execute(event, cmd, wait=False): def register(obj, button=None, cmd=None, wait=False): event_id = __event_id(obj.id if obj is not None else "", button) logging.debug("registering callback {}".format(event_id)) + core.event.unregister(event_id) # make sure there's always only one input event if callable(cmd): core.event.register(event_id, cmd) else: diff --git a/tests/core/test_input.py b/tests/core/test_input.py index 962b5b2..a12deb2 100644 --- a/tests/core/test_input.py +++ b/tests/core/test_input.py @@ -59,14 +59,14 @@ def test_different_events(obj, obj2, cb, cb2): 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"], cb2) core.input.trigger(event(obj)) - cb.assert_called_once_with(event(obj)) cb2.assert_called_once_with(event(obj)) + cb.assert_not_called() def test_event_names():